diff options
169 files changed, 15264 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c219394 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.user +Makefile* +*.obj +*.pdb +moc_* +ui_* + diff --git a/doc/classic.css b/doc/classic.css new file mode 100644 index 0000000..f97bdbe --- /dev/null +++ b/doc/classic.css @@ -0,0 +1,295 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Arial, Geneva, Helvetica, sans-serif; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} + +h3.fn,span.fn +{ + background-color: #eee; + border-width: 1px; + border-style: solid; + border-color: #ddd; + font-weight: bold; + padding: 6px 0px 6px 10px; + margin: 42px 0px 0px 0px; +} + +hr { + border: 0; + color: #a0a0a0; + background-color: #ccc; + height: 1px; + width: 100%; + text-align: left; + margin: 34px 0px 34px 0px; +} + +table.valuelist { + border-width: 1px 1px 1px 1px; + border-style: solid; + border-color: #dddddd; + border-collapse: collapse; + background-color: #f0f0f0; +} + +table.indextable { + border-width: 1px 1px 1px 1px; + border-collapse: collapse; + background-color: #f0f0f0; + border-color:#555; + font-size: 110%; +} + +table td.largeindex { + border-width: 1px 1px 1px 1px; + border-collapse: collapse; + background-color: #f0f0f0; + border-color:#555; + font-size: 120%; +} + +table.valuelist th { + border-width: 1px 1px 1px 2px; + padding: 4px; + border-style: solid; + border-color: #666; + color:white; + background-color:#666; +} + +th.titleheader { + border-width: 1px 0px 1px 0px; + padding: 4px; + border-style: solid; + border-color: #444; + color:white; + background-color:#555555; + font-size: 110%; +} + +th.largeheader { + border-width: 1px 0px 1px 0px; + padding: 4px; + border-style: solid; + border-color: #444; + color:white; + background-color:#555555; + font-size: 120%; +} + +p { + + margin-left: 4px; + margin-top: 8px; + margin-bottom: 8px; +} + +a:link +{ + color: #0046ad; + 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 +} + +body +{ + background: #ffffff; + color: black +} + +table.generic, table.annotated +{ + border-width: 1px; + border-color:#bbb; + border-style:solid; + border-collapse:collapse; +} + +table td.memItemLeft { + width: 180px; + padding: 2px 0px 0px 8px; + margin: 4px; + border-width: 1px; + border-color: #E0E0E0; + border-style: none; + font-size: 100%; + white-space: nowrap +} + +table td.memItemRight { + padding: 2px 8px 0px 8px; + margin: 4px; + border-width: 1px; + border-color: #E0E0E0; + border-style: none; + font-size: 100%; +} + +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: 0px; + padding-bottom: 0px; + padding-left: 0px; + padding-right: 0px; + 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 +} + +.qmlitem { + padding: 0; +} + +.qmlname { + white-space: nowrap; + font-weight: bold; + font-size: 125%; +} + +.qmltype { + font-weight: bold; + font-size: 125%; +} + +.qmlproto, .qmldoc { + // border-top: 1px solid #84b0c7; +} + +.qmlproto { + padding: 0; + //background-color: #e4e4e4;//#d5e1e8; + //font-weight: bold; + //-webkit-border-top-left-radius: 8px; + //-webkit-border-top-right-radius: 8px; + //-moz-border-radius-topleft: 8px; + //-moz-border-radius-topright: 8px; +} + +.qmldoc { + border-top: 1px solid #e4e4e4; + //padding: 2px 5px; + //background-color: #eef3f5; + //border-top-width: 0; + //-webkit-border-bottom-left-radius: 8px; + //-webkit-border-bottom-right-radius: 8px; + //-moz-border-radius-bottomleft: 8px; + //-moz-border-radius-bottomright: 8px; +} + +.qmldoc p, .qmldoc dl, .qmldoc ul { + //margin: 6px 0; +} + +*.qmlitem p { + //margin-top: 0px; + //margin-bottom: 0px; +} diff --git a/doc/doc.pri b/doc/doc.pri new file mode 100644 index 0000000..dcaa495 --- /dev/null +++ b/doc/doc.pri @@ -0,0 +1,51 @@ +# Adapted from doc/doc.pri in Qt Creator. + +QDOC_BIN = $$[QT_INSTALL_BINS]/qdoc3 +win32:QDOC_BIN = $$replace(QDOC_BIN, "/", "\\") + +unix { + QDOC = SRCDIR=$$PWD OUTDIR=$$OUT_PWD/doc/html QT_MOBILITY_SOURCE_PATH=$$QT_MOBILITY_SOURCE_PATH $$QDOC_BIN + HELPGENERATOR = $$[QT_INSTALL_BINS]/qhelpgenerator +} else { + QDOC = set SRCDIR=$$PWD&& set OUTDIR=$$OUT_PWD/doc/html&& set QT_MOBILITY_SOURCE_PATH=$$QT_MOBILITY_SOURCE_PATH&& $$QDOC_BIN + # Always run qhelpgenerator inside its own cmd; this is a workaround for + # an unusual bug which causes qhelpgenerator.exe to do nothing + HELPGENERATOR = cmd /C $$replace($$list($$[QT_INSTALL_BINS]/qhelpgenerator.exe), "/", "\\") +} + +QHP_FILE = $$OUT_PWD/doc/html/simulator.qhp +QCH_FILE = $$OUT_PWD/doc/simulator.qch + +unix { +html_docs.commands = $$QDOC $$PWD/simulator.qdocconf +} else { +html_docs.commands = \"$$QDOC $$PWD/simulator.qdocconf\" +} +html_docs.depends += $$PWD/simulator.qdoc $$PWD/scripting.qdoc $$PWD/simulator.qdocconf +html_docs.files = $$QHP_FILE + +qch_docs.commands = $$HELPGENERATOR -o $$QCH_FILE $$QHP_FILE +qch_docs.depends += html_docs +qch_docs.files = $$QCH_FILE + +unix:!macx { + qch_docs.path = $$PREFIX/doc + qch_docs.CONFIG += no_check_exist + INSTALLS += qch_docs +} + +macx { + DOC_DIR = "$${OUT_PWD}/bin/Simulator.app/Contents/Resources/doc" + cp_docs.commands = mkdir -p \"$${DOC_DIR}\" ; $${QMAKE_COPY} \"$${QCH_FILE}\" \"$${DOC_DIR}\" + cp_docs.depends += qch_docs + docs.depends = cp_docs + QMAKE_EXTRA_TARGETS += html_docs qch_docs cp_docs docs +} +!macx { + docs.depends = qch_docs + QMAKE_EXTRA_TARGETS += html_docs qch_docs docs +} + +OTHER_FILES = $$PWD/simulator.qdoc \ + $$PWD/scripting.qdoc \ + $$PWD/simulator.qdocconf diff --git a/doc/fixnavi.pl b/doc/fixnavi.pl new file mode 100755 index 0000000..bf6acaa --- /dev/null +++ b/doc/fixnavi.pl @@ -0,0 +1,70 @@ +#! /usr/bin/perl -w + +use strict; + +@ARGV == 1 or die "usage: $0 <qdoc-file>\n"; +my $file = $ARGV[0]; +open FILE, $file or die "File $file cannot be opened.\n"; +my @toc = (); +my %title2page = (); +my $doctitle = ""; +my $curpage = ""; +my $intoc = 0; +while (<FILE>) { + if (keys(%title2page) == 1 && /^\h*\\list/) { + $intoc++; + } elsif (!$intoc) { + if (/^\h*\\page\h+(\H+)/) { + $curpage = $1; + } elsif (/^\h*\\title\h+(.+)$/) { + if ($curpage eq "") { + die "Title '$1' appears in no \\page.\n"; + } + $title2page{$1} = $curpage; + $doctitle = $1 if (!$doctitle); + $curpage = ""; + } + } else { + if (/^\h*\\endlist/) { + $intoc--; + } elsif (/^\h*\\o\h+\\l\h*{(.*)}$/) { + push @toc, $1; + } + } +} +close FILE; + +my %prev = (); +my %next = (); +my $last = $doctitle; +for my $title (@toc) { + $next{$last} = $title2page{$title}; + $prev{$title} = $title2page{$last}; + $last = $title; +} + +open IN, $file or die "File $file cannot be opened a second time?!\n"; +open OUT, '>'.$file.".out" or die "File $file.out cannot be created.\n"; +my $cutting = 0; +while (<IN>) { + if (!$cutting) { + if (/^\h*\\contentspage/) { + $cutting = 1; + } + } else { + if (/^\h*\\title\h+(.+)$/) { + print OUT " \\previouspage ".$prev{$1} if ($prev{$1}); + print OUT " \\page ".$title2page{$1}; + print OUT " \\nextpage ".$next{$1} if ($next{$1}); + print OUT "\n"; + $cutting = 0; + } else { + next; + } + } + print OUT $_; +} +close OUT; +close IN; + +rename($file.".out", $file) or die "Cannot replace $file with new version.\n"; diff --git a/doc/images/accelerometer-sensor.png b/doc/images/accelerometer-sensor.png Binary files differnew file mode 100644 index 0000000..ef30d87 --- /dev/null +++ b/doc/images/accelerometer-sensor.png diff --git a/doc/images/attitude-sensor.png b/doc/images/attitude-sensor.png Binary files differnew file mode 100644 index 0000000..2b642d9 --- /dev/null +++ b/doc/images/attitude-sensor.png diff --git a/doc/images/location-info.png b/doc/images/location-info.png Binary files differnew file mode 100644 index 0000000..41ea01d --- /dev/null +++ b/doc/images/location-info.png diff --git a/doc/images/qt-creator-project-button.png b/doc/images/qt-creator-project-button.png Binary files differnew file mode 100644 index 0000000..94eba95 --- /dev/null +++ b/doc/images/qt-creator-project-button.png diff --git a/doc/images/qt-logo.png b/doc/images/qt-logo.png Binary files differnew file mode 100644 index 0000000..3e2e480 --- /dev/null +++ b/doc/images/qt-logo.png diff --git a/doc/images/qt-simulator-application.png b/doc/images/qt-simulator-application.png Binary files differnew file mode 100644 index 0000000..5dd165d --- /dev/null +++ b/doc/images/qt-simulator-application.png diff --git a/doc/images/qt-simulator-battery.png b/doc/images/qt-simulator-battery.png Binary files differnew file mode 100644 index 0000000..0fe17cd --- /dev/null +++ b/doc/images/qt-simulator-battery.png diff --git a/doc/images/qt-simulator-contacts.png b/doc/images/qt-simulator-contacts.png Binary files differnew file mode 100644 index 0000000..3689374 --- /dev/null +++ b/doc/images/qt-simulator-contacts.png diff --git a/doc/images/qt-simulator-devices.png b/doc/images/qt-simulator-devices.png Binary files differnew file mode 100644 index 0000000..e6f0864 --- /dev/null +++ b/doc/images/qt-simulator-devices.png diff --git a/doc/images/qt-simulator-drives.png b/doc/images/qt-simulator-drives.png Binary files differnew file mode 100644 index 0000000..913f688 --- /dev/null +++ b/doc/images/qt-simulator-drives.png diff --git a/doc/images/qt-simulator-generic-settings.png b/doc/images/qt-simulator-generic-settings.png Binary files differnew file mode 100644 index 0000000..aa6f1e6 --- /dev/null +++ b/doc/images/qt-simulator-generic-settings.png diff --git a/doc/images/qt-simulator-location.png b/doc/images/qt-simulator-location.png Binary files differnew file mode 100644 index 0000000..88bc55d --- /dev/null +++ b/doc/images/qt-simulator-location.png diff --git a/doc/images/qt-simulator-messaging.png b/doc/images/qt-simulator-messaging.png Binary files differnew file mode 100644 index 0000000..ac02f5d --- /dev/null +++ b/doc/images/qt-simulator-messaging.png diff --git a/doc/images/qt-simulator-network.png b/doc/images/qt-simulator-network.png Binary files differnew file mode 100644 index 0000000..ae74c1e --- /dev/null +++ b/doc/images/qt-simulator-network.png diff --git a/doc/images/qt-simulator-quick-tour.png b/doc/images/qt-simulator-quick-tour.png Binary files differnew file mode 100644 index 0000000..651c240 --- /dev/null +++ b/doc/images/qt-simulator-quick-tour.png diff --git a/doc/images/qt-simulator-scripting.png b/doc/images/qt-simulator-scripting.png Binary files differnew file mode 100644 index 0000000..cf816d0 --- /dev/null +++ b/doc/images/qt-simulator-scripting.png diff --git a/doc/images/qt-simulator-search-advanced.png b/doc/images/qt-simulator-search-advanced.png Binary files differnew file mode 100644 index 0000000..55fb83a --- /dev/null +++ b/doc/images/qt-simulator-search-advanced.png diff --git a/doc/images/qt-simulator-sensors.png b/doc/images/qt-simulator-sensors.png Binary files differnew file mode 100644 index 0000000..bd151de --- /dev/null +++ b/doc/images/qt-simulator-sensors.png diff --git a/doc/images/qt-simulator-view-settings.png b/doc/images/qt-simulator-view-settings.png Binary files differnew file mode 100644 index 0000000..89b4bc9 --- /dev/null +++ b/doc/images/qt-simulator-view-settings.png diff --git a/doc/images/qt-simulator.png b/doc/images/qt-simulator.png Binary files differnew file mode 100644 index 0000000..87cf626 --- /dev/null +++ b/doc/images/qt-simulator.png diff --git a/doc/scripting.qdoc b/doc/scripting.qdoc new file mode 100644 index 0000000..7cc3813 --- /dev/null +++ b/doc/scripting.qdoc @@ -0,0 +1,4 @@ +/*! + \class LocationScriptInterface + \brief Exposed as location. +*/ diff --git a/doc/simulator.qdoc b/doc/simulator.qdoc new file mode 100644 index 0000000..27b2ada --- /dev/null +++ b/doc/simulator.qdoc @@ -0,0 +1,992 @@ +// ********************************************************************** +// NOTE: the sections are not ordered by their logical order to avoid +// reshuffling the file each time the index order changes (i.e., often). +// Run the fixnavi.pl script to adjust the links to the index order. +// ********************************************************************** + +/*! + \contentspage{index.html}{Simulator} + \page index.html + \nextpage simulator-description.html + + \title Qt Simulator Manual + + \section1 Version 0.9.0 (1.0.0 Beta) + + With Qt Simulator, you can test Qt applications that are intended for + mobile devices in an environment similar to that of the device. You can + change the information that the device has about its configuration and + environment. + + \image qt-simulator.png "Qt Simulator" + + \note Please report bugs and suggestions to the + \l{http://bugreports.qt.nokia.com}{JIRA task tracker}. + + \list + \o \l{Introducing Qt Simulator} + \o \l{Starting Qt Simulator} + \o \l{Quick Tour} + \o \l{Simulating Device Use} + \o \l{Simulating Networking} + \o \l{Simulating Location} + \o \l{Simulating Storage Devices} + \o \l{Importing Contacts} + \o \l{Simulating Messaging} + \o \l{Simulating Sensors} + \o \l{Testing Applications Using the Qt Mobility Service Framework} + \o \l{Interacting with Applications} + \o \l{Checking Application Layout} + \o \l{Scripting} + \o \l{Adding New Device Models} + \o \l{Known Issues} + \endlist +*/ + +/*! + + \contentspage index.html + \previouspage simulator-starting.html + \page simulator-quick-tour.html + \nextpage simulator-generic.html + + \title Quick Tour + + This section describes the Qt Simulator interface and the most important tasks + that you can perform with Qt Simulator. + + \image qt-simulator-quick-tour.png "Device Control dialog" + + Qt Simulator displays a device with the application open on the screen. To interact with + the application, use the mouse and keyboard. To move the device window, drag the device + frame. + + The \gui{Device Control} dialog provides the following controls: + + \list + + \o \gui{Quick access buttons} - Check how the application handles changes in device + state, such as battery level, network mode, signal strength, and power state. Run your + favorite scripts. + + \o \gui{Device settings} - Adjust the properties of the simulated + device. To filter the list, enter a setting name into the search + field. Click the buttons next to the tabs to show advanced and rarely used settings. + + \image qt-simulator-search-advanced.png "Search field and Advanced settings button" + + \o \gui{Application settings} - Manage applications running on Qt Simulator. + + \image qt-simulator-application.png "Application view" + + \o \gui{View settings} - See how the application looks on different devices. + Change the device to be simulated, rotate the device, or change the display + resolution and size. Move the zoom slider to the left to scale the device + to its real size and to the right to make each device pixel correspond to + a pixel of your screen. + + \image qt-simulator-view-settings.png "View settings" + + \endlist*/ + +/*! + + \contentspage index.html + \previouspage simulator-description.html + \page simulator-starting.html + \nextpage simulator-quick-tour.html + + \title Starting Qt Simulator + + You can start Qt Simulator directly from Qt Creator to quickly test and debug + applications: + + \list 1 + + \o Create a Qt Creator project. + + \o In the \gui{Projects} mode, \gui{Build Settings}, click \gui{Add} to + add a new build configuration. + + \o In the \gui{Configuration Name} field, enter a name for the configuration. + + \o In the \gui{Qt Version} field, select the Simulator Qt version. + + \o Click \gui{Make Active} to activate the new build configuration. + + \o Click the \gui{+} button to add \gui{Simulator} as a target. + + \o Click the \gui{Play} button to build and run the application. + + \endlist + + \section1 Switching Between Build Configurations + + To switch between build configurations in Qt Creator, click the \gui{Project} + button and select a project: + + \image qt-creator-project-button.png "Project button" + + The button shows the name of your project and the + currently active build configuration. + +*/ + + + +/*! + \contentspage index.html + \previouspage simulator-quick-tour.html + \page simulator-generic.html + \nextpage simulator-networking.html + + \title Simulating Device Use + + \image qt-simulator-generic-settings.png "Generic settings" + + You can use Qt Simulator to test applications that use the Qt System Info API to + access general information from the mobile device. + Mobile devices have been designed for use when mobile. Keep the characteristics of + mobile devices in mind when you create applications for them. Use Qt Simulator to + simulate the behavior of applications on different device models in different + conditions: + + \list + + \o \l{Running Out of Battery Power} + \o \l{Using Silent and Offline Profiles} + \o \l{Changing Device Language} + \o \l{Supporting Device Features} + \o \l{Accessing Services} + \o \l{Handling User Input} + \o \l{Identifying Devices} + \o \l{Using Colors} + \omit \o \l{Turning off Screen Saver} \endomit + + \endlist + + \section1 Running Out of Battery Power + + Mobile devices are not constantly connected to a power outlet, but run on battery power. + Optimize power consumption to keep the total consumption at an acceptable level and to + prevent users from running out of battery power. In addition, make sure that applications + run successfully in low-memory condition or display a clear and informative error message. + + You can write a script that decreases the battery level setting, to check how applications + behave when the device runs out of power. You can load an example script that decreases the + value for battery level, \tt{scripts/examples/runOutOfBattery.qs}. + For more information on loading scripts, see \l{Scripting}. + + You can also check how applications behave, when the mobile device is connected to a + power outlet or it is charging. + + Change the \gui{Battery level} and \gui{Power state} settings in the \gui{Generic} + section. + + \section1 Using Silent and Offline Profiles + + Profiles allow users to adjust and customize ringing tones, alert tones, and other + mobile device tones for different events, environments, or caller groups. Users can + change the active profile on their devices. + + The \gui{Offiline} profile (flight mode) prevents mobile devices from accidentally + switching on, sending, or receiving messages, or using WLAN, Bluetooth, GPS, or + FM radio. In addition, it closes any Internet connection that may be in operation + when users select the profile. + + Test applications with different profiles to make sure that: + + \list + + \o Application sounds do not override the currently selected profile. Sounds + should not play in the \gui{Silent} profile, unless the application is intended for + audio playback. + + \o Applications work correctly in the \gui{Offline} profile, with the + phone capabilities and network connections disabled. + + \endlist + + In the \gui {Generic} section, \gui{Profile} field, select profiles to test the application with a + particular profile. + + \section1 Changing Device Language + + Implement predefined texts in the application UI using logical names instead of + hard-coding them to the application. This enables localization by changing the + language packet (LOC file) that is used. + + After translation, UI texts in different languages may take up more space than the original + text. To prepare for text expansion, avoid using long and difficult UI text. + + Do not truncate the predefined UI texts even if the components may do it automatically. + This makes it difficult to understand the texts and creates a feeling of unfinished + software. + + You can fine-tune UI text strings to different display sizes by producing + separate text strings for the small and large displays (orientation, aspect ratio, + physical size). This avoids the problem of having abbreviated text strings when there + is plenty of display space available. + + When users change the language settings on the mobile device, the localized version should + be started automatically. + + Click the \gui{Advanced Settings} button to display the language settings in the + \gui{Generic} section: + + \list + + \o \gui{Language} displays the current system language as a two-letter ISO 639-1 + language code. For example, EN. + + \o \gui{Country code} displays the current system country code as a two-letter + ISO 3166-1 country code. + + \o \gui{Available languages} displays available Qt language translations as two-letter + ISO 639-1 language codes. If translations cannot be found, it displays the current system + language. + + \endlist + + Change the \gui{Language} and \gui{Country code} settings + to test that the localized versions of your application start correctly and look + and function as they should. + + Click \gui{Show} next to \gui{Available languages}, and then click \gui Add to add new + language codes. Use the ISO 639-1 language codes. + + \omit ### Is a link to the country code list needed here? \endomit + + \section1 Supporting Device Features + + Mobile devices support different sets of device features, depending on their configuration + and the underlying hardware. When you develop applications for multiple devices, you can + programmatically determine which platform, software version, languages, features, and + accessories a particular device supports. This allows you to programmatically enable and + disable application functions for a particular device. + + Change the \gui{Features} in the \gui{Generic} section to check how your + application behaves when a particular device feature is supported or not supported. + For example, devices can support several physical connection methods, such as \gui{Bluetooth}, + \gui{Infrared}, and \gui{USB} (universal serial bus) for downloading data. Devices can also + have a \gui{Memory Card} available for storing the data. + + Change the \gui{Operating System}, \gui{Qt}, and \gui{Firmware} \gui{Versions} to check + how your application behaves on a specific version. Click \gui{Change} to specify the + version. Specify firmware versions as follows: + \bold major.minor.build. If a particular version does not include the build part, set it to 0. + If a particular element is not available at all, the API returns the error + \bold {Not Installed}. + + \section1 Accessing Services + + The basis for access security is the effective identification of the users and the + equipment they are using. The device can be protected with a lock code, while the + SIM card, memory card, and applications can have their own PIN codes and passwords. + For enterprise applications, this can mean that only a specific user with a specific + application, device, memory card, and SIM card can access the corporate data. + + Devices are identified by international mobile equipment identity (IMEI) and + international mobile subscriber identity (IMSI) numbers. Change the \gui{IMEI} and + \gui{IMSI} numbers in the \gui{Generic} section to test access security for + applications. + + \section1 Handling User Input + + In order to support as many target devices as possible, applications must support + different input control configurations: + + \list + + \o Hardware keypad and touch + + \o Touch-only + + \o Hardware keypad only + + \endlist + + For devices that support both hardware keypad and touch interactions, consider which + is the best mode of interaction for the application. For touch-only devices, all + interactions should naturally be touch-optimised. + + For devices that support only the hardware keypad, touch-only components can be + flagged out of the application. This way it is possible to create applications that + will function with different device configurations. + + Change the \gui{Input methods} in the \gui{Generic} section to test how + the application handles different input methods. + + \section1 Identifying Devices + + You can specify the \gui{Manufacturer}, \gui{Model}, and \gui{Product name} to + allow applications to identify the device. You can write any values in the fields. + For example, you could set \gui{Manufacturer} to \bold {Nokia} and \gui{Model} to \bold {N97}. + + \section1 Using Colors + + Like computer monitors, mobile devices use an additive color process. Unlike print + media, which begin with a white surface, the computer screen begins as a black surface + to which colored light red, green, and blue (RGB) is added. + + Although early mobile devices supported very few colors, color support is now quite + robust, with a large proportion of devices providing 12-bit (4,096 colors), + 16-bit (65,536 colors), or 24-bit (16 million colors) color support. However, + similar to the variety in screen size, many devices in use support varying color depths, + with newer, low-cost models typically supporting 12- or 16-bit color depths. + + Applications can query the color scheme of the mobile device and adapt to it. For + example, applications can switch to a night color scheme when brightness falls + below a certain value. + + Change the \gui{Color depth} and \gui{Brightness} values in the \gui{Generic} + section to change the way the application perceives them. + + \omit + + \section1 Turning off Screen Saver + + Applications can turn off the screen saver on the mobile device. However, if the screen + saver is secure by policy, the policy is be honored and screen saver cannot be + turned off. + + As a rule, do not override screen saver settings because they work automatically + according to user-set preferences. The application can monitor the screen saver status + to detect whether the device is in active use. + + You can override the settings in special cases, such as in a navigation + application. However, the application should monitor the device status to check + whether the prerequisites are still valid. For example: + + \list + + \o Is the device connected to a power supply (charger or car kit)? + \o Does the application require lights on the foreground? + \o Is the battery level sufficient? + + \endlist + + Select the \gui {Screen saver inhibited} check box in the \gui {Generic} section + to turn off the screen saver. + + \endomit + +*/ + +/*! + \contentspage index.html + \previouspage simulator-generic.html + \page simulator-networking.html + \nextpage simulator-location.html + + \title Simulating Networking + + Mobile applications can be divided into stand-alone and client-server applications. + However, the difference is not always clear. Stand-alone applications may offer the + possibility to refresh or update information from a server, and client-server + applications may store recent information on the device, thus enabling use of the + application without server connection. + + Additionally, connection to a server can be established through a variety of services, + such as Bluetooth, WLAN, or the mobile network. If possible, the application should use + the most sensible connection method, such as a WLAN for internet connection, when + available. + + Hide the complexity of network connectivity in your applications. Short network coverage + problems should not cause loss of users' work or stop them from working. Connection + status should be displayed clearly. Synchronization should be automatic but under user + control. + + When users move around with their mobile device, the device connects to + available cells with sufficient signal strength. You can change the network settings to + test how the application handles roaming from one cell or network to another. + + You can use Qt Simulator to test applications that use the Qt Bearer Management API + to manage the connectivity state to the network. + Change the \gui{Network mode properties}, such as \gui{Status} and + \gui{Signal strength} in the \gui{Network} section. + + \image qt-simulator-network.png "Network settings" + + You can also load the \c sysinfonetwork.qs example script to test how your + application behaves when the device moves between cells with varying signal strength + in a GSM network. For more information on loading scripts, see \l{Scripting}. + +*/ + +/*! + \contentspage index.html + \previouspage simulator-networking.html + \page simulator-location.html + \nextpage simulator-drives.html + + \title Simulating Location + + Applications can use the Qt Location API to access basic geographical information + obtained from satellite or other sources about the user, including latitude and + longitude, bearing, speed and altitude. This allows you to develop a range of + geographical applications, for example, maps. + + Location-based services (LBS) use coordinates from the world geodetic system (WGS 84), + which is also used as a reference system by the global positioning system (GPS). + The coordinates are based on values for latitude, longitude, and altitude (elevation + above sea level). + + The North Pole is 90 degrees North (+90 degrees) and the South Pole is 90 degrees South + (-90 degrees). The Equator is defined as 0 degrees; locations above it have positive + latitudes (0 to +90 degrees); those below (0 to -90 degrees) negative ones. + + There are two definitions of North Pole; Magnetic North Pole and True (Geographical) + North Pole. Any application with a compass must check how the API defines North Pole. + + The Magnetic North Pole is the point to which compasses point. The True North Pole + defines latitude as +90 degrees. + + Meridians are constant longitudinal (north-south) values. The Prime (Greenwich) + Meridian's value is 0 degrees. WGS84, which LBS use, defines its zero meridian some + 100 meters east of the Prime one. Locations east of the Prime Meridian have positive + longitudinal values (0 to +180 degrees), those west (0 to -180 degrees) have negative + ones. + + Latitude lines are smaller near the poles. At the equator, one degree of longitude + is roughly 111.3 km, whereas at 60 degrees of latitude one degree of longitude is + only 55.8 km. + + \image location-info.png + + GPS connections can consume the battery power rapidly, so you should take this into + account when designing applications that access this functionality. + + To test an application that uses LBS, specify values for \gui{Latitude}, + \gui{Longitude}, and \gui{Altitude} in the \gui{Location} section. + + \image qt-simulator-location.png "Location settings" + +*/ + +/*! + \contentspage index.html + \previouspage simulator-location.html + \page simulator-drives.html + \nextpage simulator-contacts.html + + \title Simulating Storage Devices + + One or several storage devices, such as memory cards, can be added to mobile devices to increase the available + storage space. Devices may also have internal non-removable memory cards or internal mass + storage. That is, multiple drives are supported. + + Applications can use the Qt System Info API to check how much space is available in a + particular storage. To test the applications, specify + the space available on the device in the \gui{Available space} field in + \gui{Storage Properties} in the \gui{Storage} section. + + \image qt-simulator-drives.png "Storage settings" + +*/ + +/*! + \contentspage index.html + \previouspage simulator-drives.html + \page simulator-contacts.html + \nextpage simulator-messaging.html + + \title Importing Contacts + + You can use Qt Simulator to test applications that use the Qt Contacts API to access + address book information. The applications can create, edit, list, delete, and look up + contact information whether it is stored locally or remotely. + + You can use the predefined contacts in the \gui{Contacts} section to test applications. Click + \gui{Import} to import new contact information from vCard files (\c {.vcf}). + + \image qt-simulator-contacts.png "Contacts" + + The initial contact list is created from the data in \tt{stubdata/standardcontacts.vcf} + during Qt Simulator startup. The 'self' contact is read from + \tt{stubdata/standardselfcontact.vcf}. +*/ + +/*! + \contentspage index.html + \previouspage simulator-application.html + \page simulator-views.html + \nextpage simulator-scripting.html + + \title Checking Application Layout + + Unlike PC displays, which have standardised to two or three common sizes, + mobile phone displays still come in many shapes and sizes. The screens have + grown larger, while smaller screens still exist at the lower end of the market. + Displays typically support both portrait and landscape modes. + + The screen size of mobile devices is significantly smaller than that available + on desktop devices. Carefully consider what is the most relevant content to + present on the application UI, as it might not be reasonable to try and fit as + much content into the screen as you might have in a desktop application. + + Relate the position and size of widgets to the dimensions of the display. + This enables the same set of information to be presented on the screen in all + resolutions; higher resolution devices just display finer graphics. + + Change the settings in the \gui{View} section to check application + layout. + + \image qt-simulator-view-settings.png "View settings" + + \section1 Changing Device Models + + Each unique mobile device targets a different market niche, a combination of form, + functionality, and price, which expands the total addressable market for mobile + applications. The characteristics of your target devices, such as screen size and + orientation, touch support, and the availability of a keyboard or home screen, affect + application design. + + In the \gui{Device} field, select different device models to test the application + on them. + + \section1 Rotating Devices + + Rotation changes the orientation of the primary display between portrait and + landscape. Rotation is effected by a sensor or is specifically disabled in the + device configuration. Additionally, you can disable rotation in applications + by using the forced orientation application property. + + By default, all applications can present in portrait or landscape orientation. + Based on the product ID, one orientation is considered dominant. Because most + application software must deploy to multiple devices, ensure that your + application layout is properly usable in both orientations. + + Click \gui{Rotate Device} to change the orientation of the display between + portrait and landscape. + + \section1 Changing Screen Resolution + + In addition to the display size in pixels, physical screen dimensions have an + impact on designs. Devices with the same size display can vary in physical + dimensions and, consequently, in screen resolution. The implications are most + obvious on images, particularly on those that contain graphic text or fine details. + For example, on devices that share a 240-pixel screen width, a logo that is legible + at 154 pixels per inch may be somewhat less so at 199 pixels per inch. + + You can use Qt Simulator to ensure that screens designed on a large computer monitor + are suitable once transferred to a mobile device and that critical visual elements + remain legible at all supported screen sizes. + + Move the \gui{Zoom} slider to the left to scale the device to its real size and to the + right to make each device pixel correspond to a pixel on the screen. However, Windows + always reports the DPI of the screen as 96 pixels per inch, and therefore, Qt Simulator + cannot reliably detect the DPI of the screen. The same problem might arise on some Linux systems + that use a fixed value for the DPI. + + Click the \gui {Advanced Settings} button to make the \gui {Native size} + setting match the real size of the device. In the \gui Configuration dialog, + you can use the following approaches + to scale the screen to the correct size: + + \list + + \o In the \gui {Diagonal in inches} field, enter the diagonal of the display + in inches. + + \o In the \gui {Manual Correction} group, place a ruler next to the line, + and then move the slider to the 10 inch or 4 centimeter mark on the ruler. + + \o In the \gui {Correction Factor} field, enter a value to scale the + screen. This value is adjusted automatically when you edit the other + fields. + + \endlist + + Qt Simulator scales fonts according to the screen DPI. Always specify font size in points, + not pixels, to have them scaled correctly on different screen sizes. + + \omit ### Add an image of a screen in both ends of the scale\endomit + + + +*/ + +/*! + \contentspage index.html + \previouspage index.html + \page simulator-description.html + \nextpage simulator-starting.html + + \title Introducing Qt Simulator + + Qt Simulator allows you to quickly test and debug applications that + target mobile devices, without the overhead of emulating the device + at hardware level. It provides special versions of the Qt and + Qt Mobility libraries that forward the display and settings to it. + + You can link applications that use the Qt and Qt Mobility APIs to these + libraries to run them inside Qt Simulator. This allows you to see how applications + look and function on different devices in different situations. For example, you can + view the application layout on Symbian and Maemo devices, in both landscape and + portrait orientation. Or you can check how your application behaves when + device battery power decreases to low or critical level. + + \image qt-simulator-devices.png "Symbian non-touch and Maemo devices" + + Qt Simulator does not support any device specific APIs by design. Therefore, + applications that run well on Qt Simulator also run on any device that hosts the + Qt and Qt Mobility libraries. + + The following Qt Mobility components are supported: + \list + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/bearer-management.html}{Bearer Management} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/contacts.html}{Contacts} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/location-overview.html}{Location} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/messaging.html}{Messaging} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/publ-subs.html}{Publish and Subscribe} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/service-frameworks.html}{Qt Service Framework} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/sensors-api.html}{Sensors} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/systeminfo.html}{System Information} + \o \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/versit.html}{Versit} + \endlist +*/ + +/*! + \contentspage index.html + \previouspage simulator-views.html + \page simulator-scripting.html + \nextpage simulator-adding-models.html + + \title Scripting + + The Qt Simulator JavaScript interface enables you to automate recurring + sets of changes or to simulate a continuously changing environment. + + \image qt-simulator-scripting.png "Scripting" + + \section1 Locating Scripts + + Create a script (.js or .qs) that sets the device to its desired state when you + open an application in Qt Simulator. Place the script in the \tt{scripts/autostart/} + folder to run it automatically when Qt Simulator starts. + + You can then use the \gui{Device Control} dialog to change the default + settings according to your test cases. To run the same tests repeatedly + or to test complicated sequences of events, create scripts and place them in + the \tt{scripts} folder. + + Place you favorite scripts in the \tt{scripts/favorites/} folder. + + Example scripts are located in \tt{scripts/examples/}. + + \section1 Running Scripts + + To run a script: + + \list 1 + + \o Click the \gui{JS} quick access button to + bring up a list of scripts in the \tt{scripts/favorites/} folder. + + \o Double-click a script in the \gui{Scripting} tab that shows + the scripts in the \tt{scripts/} folder. + + \o Place a script in the \tt{scripts/autostart} folder to run it when Qt Simulator + starts. + + \o Add the \c {-runscript <script file>} parameter to a call of the Qt Simulator application + on the command line to trigger the execution of a script in the currently running Qt Simulator + instance externally. + + \endlist + + The \gui{Active scripts} field shows a list of currently active scripts. + To pause or resume a script, select it and click \gui{Pause}. To abort a script, + select it and click \gui{Abort}. + + + \section1 Function Reference + + The following objects and functions are added to the common JavaScript global scope: + \list + \o yield(ms): delay execution of this script for the given number of milliseconds + \o simulator: \l{SimulatorScriptInterface} + \o location: \l{LocationScriptInterface} + \o sensors: \l{SensorsScriptInterface} + \o sysinfo.generic: \l{GenericSystemInfoScriptInterface} + \o sysinfo.network: \l{NetworkSystemInfoScriptInterface} + \o sysinfo.storage: \l{StorageSystemInfoScriptInterface} + \endlist +*/ + +/*! + \contentspage index.html + \previouspage simulator-scripting.html + \page simulator-adding-models.html + \nextpage simulator-known-issues.html + + \title Adding New Device Models + + Qt Simulator contains predefined configuration files for several Nokia devices. + You can add devices by creating configuration files that specify the screen + size. That is, the size of the area on which Qt Simulator draws the + application. You can also add an image of the device in PNG format. + In the configuration file, specify the position of the screen within the image. + + The graphics and settings for the device models are stored in the \c {models/} + folder next to your Qt Simulator executable. To add a new device, create a subfolder + and put a \c {\<your device name\>.config} file into it. It is easiest to + copy and modify one of the existing files. + + Device configuration files have a key:value syntax, with the following valid keys: + \list + \o \c {name:\<string\>} - required. Name to show in the device selection + drop down menu. + + \o \c {resolutionWidth:\<integer\>} - required. Width of the device screen. + + \o \c {resolutionHeight:\<integer\>} - required. Height of the device screen. + + \o \c {diagonalInInch:\<float\>} - required. Length of the screen diagonal + in inches. + + \o \c {mockup:\<path\>} - required. Path to the image for the device. + Relative to the \c{.config} file. + + \o \c {offsetX:\<integer\>} - required. Offset of the screen top left + corner from the top left corner of the mockup image. + + \o \c {offsetY:\<integer\>} - required. Offset of the screen top left + corner from the top left corner of the mockup image. + + \o \c{defaultFontSize:\<integer\>} - optional (default: 12). Font size the + device uses if it is not set explicitly. + + \o \c {forceDpi:\<integer\>} - optional. Renders the screen by using + this DPI value instead of the physical DPI computed from the + \c {diagonalInInch} value. + + \o \c {style:\<string\>} - optional. Use this Qt style for applications running + in Qt Simulator. + + \o \c {button:\<key name\>,\<key text\>,\<x\>,\<y\>,\<width\>,\<height\>} - + optional, may be used more than once. When the user clicks inside the + rectangle defined by \c {x,y,width,height} send the key specified by \c {key name} and + \c {key text} to the application. \c {key name} must be the name of a value in the + Qt::Keys enum. \c {key text} is the value the \c {text()} member of the generated + QKeyEvent returns. + \endlist + + In addition to that, it is possible to run a script whenever your device is chosen in the + device selection. Therefore just add a file named + <name of your device (given in the .config file)>.qs to \c {scripts/devices}. +*/ + +/*! + \contentspage index.html + \previouspage simulator-adding-models.html + \page simulator-known-issues.html + + \title Known Issues + + In Linux, if hardware acceleration for graphics is not available, black + corners appear around the device and the background turns black when rotating + the device. +*/ + +/*! + \contentspage index.html + \previouspage simulator-contacts.html + \page simulator-messaging.html + \nextpage simulator-sensors.html + + \title Simulating Messaging + + The term messaging comprises text messaging, picture messaging, multimedia messaging, + instant messaging, and e-mail. Text messaging is enabled by the Short Message Service (SMS). + When providing email services to mobile device users, mobile devices rely upon the services + provided by remote e-mail servers. They support the POP3, IMAP4 and SMTP protocols for + connecting to these servers. + + You can use Qt Simulator to test applications that use the Qt Mobility Messaging API to + access messaging services to search and sort messages, notify of changes to messages stored, + send messages with or without attachments, retrieve message data, and launch the preferred + messaging client to either display an existing message, or compose a message. + + In the \gui{Messaging} section, click \gui {Trigger} to trigger incoming email or SMS from + a random person in the contact list. + + \image qt-simulator-messaging.png "Messaging section" + + Click \gui{Import} to import a whole + directory of email messages that are stored in maildir format. + + During startup, Qt Simulator imports the directory \tt{stubdata/standardmessages/}. + +*/ + +/*! + \contentspage index.html + \previouspage simulator-messaging.html + \page simulator-sensors.html + \nextpage simulator-serviceframework.html + + \title Simulating Sensors + + Mobile devices contain built-in sensors, such as an accelerometer, a compass, and ambient + light or proximity sensors. The availability of sensors depends on the device model. + + The following types of interaction can be enabled by using the sensors on the device: + + \list + + \o Changing application settings based on the ambient light conditions, such as + bright sunshine or night time. + + \o Changing the screen orientation on the device from portrait to landscape as + the device is rotated. + + \o Silencing an incoming call when the device orientation is changed (for example, on a + table) from screen down to screen up and back again. + + \o Allowing movement gestures, such as device rotation, to trigger an action. + + \o In a map application, changing the orientation of a map based on the device + compass orientation. + + \o Triggering an action when the device comes in close proximity to the user's hand + or head. + + \endlist + + You can test applications that use the Qt Mobility Sensors API in the Qt Simulator. + The \gui{Sensors} section contains controls to set the values the sensors currently + return. + + \image qt-simulator-sensors.png "Sensors section" + + \section1 Changing Light Conditions + + Specify the ambient light state in the \gui {Ambient light} field. + + \section1 Device Movement + + The accelerometer sensor channel detects movement gestures, such as moving a mobile + device up or down. The three-dimensional Cartesian coordinate system is used to + illustrate direction of the acceleration, as shown in the figure below. The x and y axes + define a plane where z-axis direction is perpendicular to the xy plane. When a device moves + along an axis in the positive direction, the acceleration is positive. When the device + moves in the negative direction, the acceleration is negative. For example, when a device + moves along the x-axis to the direction of -x, the acceleration is negative. + + \image accelerometer-sensor.png + + A mobile device placed screen up on a desk experiences a force of approximately 9.8 on + the z axis (that is, upwards). This is the proper acceleration the device experiences + relative to freefall. + + To simulate movement of the device, use the sliders to specify values for the x, y, + and z axis in the \gui {Accelerometer x}, \gui {Accelerometer y}, and \gui {Accelerometer z} + fields. + + \section1 Device Rotation + + The attitude sensor detects the rotation of the device around the x, y, or z axis: + + \list + + \o Pitch of the device is the rotation around the x axis + \o Roll is the rotation around the y axis + \o Yaw is the rotation around the z axis + + \image attitude-sensor.png + + \endlist + + Pitch and roll are zero (0) when the phone lies flat, screen up. Yaw is 0 when the top of the + device points towards the reference point. Yaw requires a fixed, external reference point + that the device can detect. For example, devices with a compass may use magnetic north as a + reference point. Devices that cannot detect a fixed, external reference point always + return 0 for yaw. + + Use the sliders to set the \gui {Attitude pitch}, \gui {Attitude roll}, and + \gui {Attitude yaw} values to test how the application handles the interaction + related to rotating the device. + + \section1 Compass Orientation + + The compass returns the azimuth of the device as degrees from magnetic north in a clockwise + direction based on the top of the device. + + \note The top of the device is a fixed point and may not represent the orientation that the + user is holding the device in. + + The calibration status of the device must be accurate for the azimuth to be accurate. + It takes some time to calibrate the magnetic north sensor and, even after being calibrated, + it can become uncalibrated. So, for an application to be sure the data coming from the magnetic + north sensor channel is accurate, it must monitor changes in the calibration property and + inform the user if something needs to be done to recalibrate the sensor. + + Use sliders to set the \gui {Compass calibration level} and \gui {Compass azimuth} values. + + \section1 Proximity + + Proximity indicates how far away from the device the user is. Use the button to toggle between + \gui {Near} and \gui {Far} distance. + + \section1 Using a Fixed Timestamp + + Many sensors update frequently, and therefore sensor readings done by the client + application contain a fresh timestamp by default. To disable that and provide a fixed timestamp + manually, select the \gui Override radio button in the \gui Timestamp group and specify + a date and time. + +*/ + +/*! + \contentspage index.html + \previouspage simulator-sensors.html + \page simulator-serviceframework.html + \nextpage simulator-application.html + + \title Testing Applications Using the Qt Mobility Service Framework + + The \l{http://qt.nokia.com/doc/qtmobility-1.0-beta/service-frameworks.html}{Qt Service Framework} + defines a unified way of finding, implementing and accessing services across multiple + platforms. + + A service is an independent component that allows a client to perform a well-defined + operation. Clients can find services based on their name and version as well as the + interface that is implemented by the service object. Once the service has been identified, + the framework starts the service and returns a pointer to it. Services are implemented as plugins. + + You can use the service framework to unify and access multiple platform specific service + implementations via the same Qt-based client application. However, + the service database is not shared between desktop applications and applications compiled + for the Qt Simulator. Therefore, to test client applications using the service framework + on Qt Simulator, you must use the \c{servicefw} command-line application + \omit Ship it! Path? \endomit to register a service. + + To tell Qt where to look for plugins, either add them to the search path by calling + QCoreApplication::addLibraryPath() or set the QT_PLUGIN_PATH. +*/ + + +/*! + \contentspage index.html + \previouspage simulator-serviceframework.html + \page simulator-application.html + \nextpage simulator-views.html + + \title Interacting with Applications + + You can run several applications simultaneously in Qt Simulator. They can be managed + in the \gui Applications view. + + \image qt-simulator-application.png "Application view" + + The title of the active application is displayed in the \gui {Topmost widget's title} + field. + + To test menu commands, click them in the \gui {Application's menu bar} field. + The actions are simulated on the device screen. + + To quit the active application, click \gui Quit. + +*/ diff --git a/doc/simulator.qdocconf b/doc/simulator.qdocconf new file mode 100644 index 0000000..f67be6f --- /dev/null +++ b/doc/simulator.qdocconf @@ -0,0 +1,222 @@ +# Run qdoc from the directory that contains this file. + +project = simulator +description = "Qt Simulator Manual" + +headers = \ + $$SRCDIR/../src/ui/sensorsui.h \ + $$SRCDIR/../src/ui/systeminfogenericui.h \ + $$SRCDIR/../src/ui/systeminfostorageui.h \ + $$SRCDIR/../src/ui/systeminfonetworkui.h \ + $$SRCDIR/../src/ui/configurationwidget.h \ + $$SIMULATOR_DEPENDENCY_PATH/include/remotecontrolwidget/locationui.h +sources = \ + $$SRCDIR/../src/ui/sensorsui.cpp \ + $$SRCDIR/../src/ui/systeminfogenericui.cpp \ + $$SRCDIR/../src/ui/systeminfostorageui.cpp \ + $$SRCDIR/../src/ui/systeminfonetworkui.cpp \ + $$SRCDIR/../src/ui/configurationwidget.cpp +headerdirs = +sourcedirs = $SRCDIR +imagedirs = $SRCDIR/images +outputdir = $OUTDIR +exampledirs = $SRCDIR +indexes = qt.index + +extraimages.HTML = qt-logo + +sources.fileextensions = "simulator.qdoc scripting.qdoc" + + +qhp.projects = Simulator +qhp.Simulator.file = simulator.qhp +qhp.Simulator.namespace = com.nokia.qt.simulator.090 +qhp.Simulator.virtualFolder = doc +qhp.Simulator.indexTitle = Qt Simulator +qhp.Simulator.indexRoot = +qhp.Simulator.extraFiles = classic.css \ + images/qt-logo.png +qhp.Simulator.filterAttributes = simulator + +qhp.Simulator.subprojects = scripting +qhp.Simulator.subprojects.scripting.title = Scripting +qhp.Simulator.subprojects.scripting.indexTitle = Simulator Scripting +qhp.Simulator.subprojects.scripting.selectors = class +qhp.Simulator.subprojects.scripting.sortPages = true + +# macros.qdocconf + +macro.aring.HTML = "å" +macro.Auml.HTML = "Ä" +macro.author = "\\bold{Author:}" +macro.br.HTML = "<br />" +macro.BR.HTML = "<br />" +macro.aacute.HTML = "á" +macro.eacute.HTML = "é" +macro.iacute.HTML = "í" +macro.gui = "\\bold" +macro.hr.HTML = "<hr />" +macro.key = "\\bold" +macro.menu = "\\bold" +macro.note = "\\bold{Note:}" +macro.oslash.HTML = "ø" +macro.ouml.HTML = "ö" +macro.QA = "\\e{Qt Assistant}" +macro.QD = "\\e{Qt Designer}" +macro.QL = "\\e{Qt Linguist}" +macro.param = "\\e" +macro.raisedaster.HTML = "<sup>*</sup>" +macro.reg.HTML = "<sup>®</sup>" +macro.return = "Returns" +macro.starslash = "\\c{*/}" +macro.uuml.HTML = "ü" +macro.mdash.HTML = "—" + +# compat.qdocconf + +alias.i = e +alias.include = input + +macro.0 = "\\\\0" +macro.b = "\\\\b" +macro.n = "\\\\n" +macro.r = "\\\\r" +macro.i = "\\o" +macro.i11 = "\\o{1,1}" +macro.i12 = "\\o{1,2}" +macro.i13 = "\\o{1,3}" +macro.i14 = "\\o{1,4}" +macro.i15 = "\\o{1,5}" +macro.i16 = "\\o{1,6}" +macro.i17 = "\\o{1,7}" +macro.i18 = "\\o{1,8}" +macro.i19 = "\\o{1,9}" +macro.i21 = "\\o{2,1}" +macro.i31 = "\\o{3,1}" +macro.i41 = "\\o{4,1}" +macro.i51 = "\\o{5,1}" +macro.i61 = "\\o{6,1}" +macro.i71 = "\\o{7,1}" +macro.i81 = "\\o{8,1}" +macro.i91 = "\\o{9,1}" +macro.img = "\\image" +macro.endquote = "\\endquotation" +spurious = "Missing comma in .*" \ + "Missing pattern .*" + +# Doxygen compatibility commands + +macro.see = "\\sa" +macro.function = "\\fn" + +# qt-cpp-ignore.qdocconf + +Cpp.ignoretokens = QAXFACTORY_EXPORT \ + QDESIGNER_COMPONENTS_LIBRARY \ + QDESIGNER_EXTENSION_LIBRARY \ + QDESIGNER_SDK_LIBRARY \ + QDESIGNER_SHARED_LIBRARY \ + QDESIGNER_UILIB_LIBRARY \ + QM_EXPORT_CANVAS \ + QM_EXPORT_DNS \ + QM_EXPORT_DOM \ + QM_EXPORT_FTP \ + QM_EXPORT_HTTP \ + QM_EXPORT_ICONVIEW \ + QM_EXPORT_NETWORK \ + QM_EXPORT_OPENGL \ + QM_EXPORT_SQL \ + QM_EXPORT_TABLE \ + QM_EXPORT_WORKSPACE \ + QM_EXPORT_XML \ + QT_ASCII_CAST_WARN \ + QT_ASCII_CAST_WARN_CONSTRUCTOR \ + QT_BEGIN_HEADER \ + QT_DESIGNER_STATIC \ + QT_END_HEADER \ + QT_FASTCALL \ + QT_WIDGET_PLUGIN_EXPORT \ + Q_COMPAT_EXPORT \ + Q_CORE_EXPORT \ + Q_EXPLICIT \ + Q_EXPORT \ + Q_EXPORT_CODECS_CN \ + Q_EXPORT_CODECS_JP \ + Q_EXPORT_CODECS_KR \ + Q_EXPORT_PLUGIN \ + Q_GFX_INLINE \ + Q_GUI_EXPORT \ + Q_GUI_EXPORT_INLINE \ + Q_GUI_EXPORT_STYLE_CDE \ + Q_GUI_EXPORT_STYLE_COMPACT \ + Q_GUI_EXPORT_STYLE_MAC \ + Q_GUI_EXPORT_STYLE_MOTIF \ + Q_GUI_EXPORT_STYLE_MOTIFPLUS \ + Q_GUI_EXPORT_STYLE_PLATINUM \ + Q_GUI_EXPORT_STYLE_POCKETPC \ + Q_GUI_EXPORT_STYLE_SGI \ + Q_GUI_EXPORT_STYLE_WINDOWS \ + Q_GUI_EXPORT_STYLE_WINDOWSXP \ + QHELP_EXPORT \ + Q_INLINE_TEMPLATE \ + Q_INTERNAL_WIN_NO_THROW \ + Q_NETWORK_EXPORT \ + Q_OPENGL_EXPORT \ + Q_OUTOFLINE_TEMPLATE \ + Q_SQL_EXPORT \ + Q_SVG_EXPORT \ + Q_SCRIPT_EXPORT \ + Q_TESTLIB_EXPORT \ + Q_TYPENAME \ + Q_XML_EXPORT \ + Q_XMLSTREAM_EXPORT \ + Q_XMLPATTERNS_EXPORT \ + QDBUS_EXPORT \ + QT_BEGIN_NAMESPACE \ + QT_BEGIN_INCLUDE_NAMESPACE \ + QT_END_NAMESPACE \ + QT_END_INCLUDE_NAMESPACE \ + PHONON_EXPORT \ + EXTENSIONSYSTEM_EXPORT \ + Q_INVOKABLE +Cpp.ignoredirectives = Q_DECLARE_HANDLE \ + Q_DECLARE_INTERFACE \ + Q_DECLARE_METATYPE \ + Q_DECLARE_OPERATORS_FOR_FLAGS \ + Q_DECLARE_PRIVATE \ + Q_DECLARE_PUBLIC \ + Q_DECLARE_SHARED \ + Q_DECLARE_TR_FUNCTIONS \ + Q_DECLARE_TYPEINFO \ + Q_DISABLE_COPY \ + QT_FORWARD_DECLARE_CLASS \ + Q_DUMMY_COMPARISON_OPERATOR \ + Q_ENUMS \ + Q_FLAGS \ + Q_INTERFACES \ + __attribute__ \ + K_DECLARE_PRIVATE \ + PHONON_OBJECT \ + PHONON_HEIR + + + +HTML.stylesheets = classic.css +HTML.postheader = "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n" \ + "<tr>\n" \ + "<td align=\"left\" valign=\"top\" width=\"32\">" \ + "<a href=\"http://qt.nokia.com/\"><img src=\"images/qt-logo.png\" align=\"left\" border=\"0\" /></a>" \ + "</td>\n" \ + "<td width=\"1\"> </td>" \ + "<td class=\"postheader\" valign=\"center\">" \ + "<a href=\"index.html\">" \ + "<font color=\"#004faf\">Home</font></a> · " \ + "</td>" \ + "</tr></table>" + +HTML.footer = "<p /><address><hr /><div align=\"center\">\n" \ + "<table width=\"100%\" cellspacing=\"0\" border=\"0\"><tr class=\"address\">\n" \ + "<td width=\"40%\" align=\"left\">Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)</td>\n" \ + "<td width=\"20%\" align=\"center\"><a href=\"trademarks.html\">Trademarks</a></td>\n" \ + "<td width=\"40%\" align=\"right\"><div align=\"right\">Qt Simulator</div></td>\n" \ + "</tr></table></div></address>" diff --git a/fonts/heiseigoths60.ttf b/fonts/heiseigoths60.ttf Binary files differnew file mode 100644 index 0000000..f63be2a --- /dev/null +++ b/fonts/heiseigoths60.ttf diff --git a/fonts/nosnb.ttf b/fonts/nosnb.ttf Binary files differnew file mode 100644 index 0000000..81f135d --- /dev/null +++ b/fonts/nosnb.ttf diff --git a/fonts/nosnr.ttf b/fonts/nosnr.ttf Binary files differnew file mode 100644 index 0000000..55d7f8d --- /dev/null +++ b/fonts/nosnr.ttf diff --git a/fonts/s60snr.ttf b/fonts/s60snr.ttf Binary files differnew file mode 100644 index 0000000..3a8404f --- /dev/null +++ b/fonts/s60snr.ttf diff --git a/fonts/s60ssb.ttf b/fonts/s60ssb.ttf Binary files differnew file mode 100644 index 0000000..8c4ce5f --- /dev/null +++ b/fonts/s60ssb.ttf diff --git a/fonts/s60tsb.ttf b/fonts/s60tsb.ttf Binary files differnew file mode 100644 index 0000000..bb4900a --- /dev/null +++ b/fonts/s60tsb.ttf diff --git a/fonts/s60zdigi.ttf b/fonts/s60zdigi.ttf Binary files differnew file mode 100644 index 0000000..c7ccf31 --- /dev/null +++ b/fonts/s60zdigi.ttf diff --git a/models/maemoFremantle/N900.png b/models/maemoFremantle/N900.png Binary files differnew file mode 100644 index 0000000..308053a --- /dev/null +++ b/models/maemoFremantle/N900.png diff --git a/models/maemoFremantle/maemoFremantle.config b/models/maemoFremantle/maemoFremantle.config new file mode 100644 index 0000000..adcea37 --- /dev/null +++ b/models/maemoFremantle/maemoFremantle.config @@ -0,0 +1,11 @@ +name:Maemo Fremantle +resolutionWidth:480 +resolutionHeight:800 +diagonalInInch:3.5 +mockup:N900.png +offsetX:72 +offsetY:165 +defaultFontSize:18 +forceDpi:96 +menu:maemoFremantle +nativeOrientation:landscape diff --git a/models/symbianNonTouch/N95_8GB.png b/models/symbianNonTouch/N95_8GB.png Binary files differnew file mode 100644 index 0000000..797b3c5 --- /dev/null +++ b/models/symbianNonTouch/N95_8GB.png diff --git a/models/symbianNonTouch/symbianNonTouch.config b/models/symbianNonTouch/symbianNonTouch.config new file mode 100644 index 0000000..db9b22f --- /dev/null +++ b/models/symbianNonTouch/symbianNonTouch.config @@ -0,0 +1,35 @@ +name:Symbian NonTouch +resolutionWidth:240 +resolutionHeight:320 +diagonalInInch:2.8 +mockup:N95_8GB.png +offsetX:27 +offsetY:66 +defaultFontSize:7 +style:s60 +button:Key_1,1,41,563,67,32 +button:Key_2,2,109,563,73,32 +button:Key_3,3,182,563,67,32 +button:Key_4,4,41,592,67,32 +button:Key_5,5,109,592,73,32 +button:Key_6,6,182,592,67,32 +button:Key_7,7,41,623,67,32 +button:Key_8,8,109,623,73,32 +button:Key_9,9,182,623,67,32 +button:Key_Asterisk,*,41,659,67,32 +button:Key_0,0,109,659,73,32 +button:Key_NumberSign,#,182,659,67,32 +button:Key_Up,,129,441,34,19 +button:Key_Down,,129,496,34,19 +button:Key_Right,,163,460,20,33 +button:Key_Left,,109,460,20,33 +button:Key_Call,,19,470,40,40 +button:Key_Hangup,,232,471,40,40 +button:Key_Context1,,21,441,83,29 +button:Key_Context2,,186,441,85,29 +button:Key_TopMenu,,49,458,57,34 +button:Key_Music,,184,459,59,34 +button:Key_Select,,128,461,35,34 +button:Key_Spell,,60,493,49,20 +button:Key_Backspace,,183,494,48,20 +nativeOrientation:portrait diff --git a/models/symbianTouch/N97.png b/models/symbianTouch/N97.png Binary files differnew file mode 100644 index 0000000..2f9237e --- /dev/null +++ b/models/symbianTouch/N97.png diff --git a/models/symbianTouch/symbianTouch.config b/models/symbianTouch/symbianTouch.config new file mode 100644 index 0000000..c68b854 --- /dev/null +++ b/models/symbianTouch/symbianTouch.config @@ -0,0 +1,14 @@ +name:Symbian Touch +resolutionWidth:360 +resolutionHeight:640 +diagonalInInch:3.5 +mockup:N97.png +offsetX:52 +offsetY:171 +defaultFontSize:7 +style:s60 +button:Key_TopMenu,,50,872,62,50 +button:Key_Call,,165,864,42,66 +button:Key_Hangup,,255,858,43,78 +menu:symbianTouch +nativeOrientation:portrait diff --git a/scripts/autostart/.directory b/scripts/autostart/.directory new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/scripts/autostart/.directory diff --git a/scripts/devices/.Maemo Fremantle.qs.swp b/scripts/devices/.Maemo Fremantle.qs.swp Binary files differnew file mode 100644 index 0000000..4c09ea2 --- /dev/null +++ b/scripts/devices/.Maemo Fremantle.qs.swp diff --git a/scripts/devices/Default.qs b/scripts/devices/Default.qs new file mode 100644 index 0000000..fdae535 --- /dev/null +++ b/scripts/devices/Default.qs @@ -0,0 +1,18 @@ +sysinfo.generic.inputMethod = sysinfo.generic.SingleTouch | sysinfo.generic.Keyboard | sysinfo.generic.Keys +sysinfo.generic.setFeature(sysinfo.generic.BluetoothFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.CameraFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.FmradioFeature, false) +sysinfo.generic.setFeature(sysinfo.generic.IrFeature, false) +sysinfo.generic.setFeature(sysinfo.generic.LedFeature, false) +sysinfo.generic.setFeature(sysinfo.generic.MemcardFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.UsbFeature, false) +sysinfo.generic.setFeature(sysinfo.generic.VibFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.WlanFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.SimFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.LocationnFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.VideoOutFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.HapticsFeature, true) +sysinfo.generic.manufacturer = "Simulator Manufacturer" +sysinfo.generic.model = "Simulator Model" +sysinfo.generic.productName = "Simulator Product Name" + diff --git a/scripts/devices/Maemo Fremantle.qs b/scripts/devices/Maemo Fremantle.qs new file mode 100644 index 0000000..570c01f --- /dev/null +++ b/scripts/devices/Maemo Fremantle.qs @@ -0,0 +1,18 @@ +sysinfo.generic.inputMethod = sysinfo.generic.SingleTouch | sysinfo.generic.Keyboard | sysinfo.generic.Keys +sysinfo.generic.setFeature(sysinfo.generic.BluetoothFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.CameraFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.FmradioFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.IrFeature, false) +sysinfo.generic.setFeature(sysinfo.generic.LedFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.MemcardFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.UsbFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.VibFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.WlanFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.SimFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.LocationnFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.VideoOutFeature, true) +sysinfo.generic.setFeature(sysinfo.generic.HapticsFeature, true) +sysinfo.generic.manufacturer = "Nokia" +sysinfo.generic.model = "iarmv7I" +sysinfo.generic.productName = "EX-51" + diff --git a/scripts/examples/devicechange.qs b/scripts/examples/devicechange.qs new file mode 100644 index 0000000..16064a3 --- /dev/null +++ b/scripts/examples/devicechange.qs @@ -0,0 +1,22 @@ +// This script shows how you can change the currently +// displayed skin +// Interesting hooks: +// simulator.deviceCount() +// simulator.setDevice(int) +// simulator.setDevice(string) +// simulator.currentDeviceName() +// simulator.currentDeviceIndex() + +var devCount = simulator.deviceCount(); +var originalName = simulator.currentDeviceName(); +messageBox("The device has " + devCount + " different skins"); + +var current = 0; +for (current = 0; current < devCount; ++current) { + simulator.setDevice(current); + messageBox("Switched to device: " + + simulator.currentDeviceName() + + " Index: " + simulator.currentDeviceIndex()); +} + +simulator.setDevice(originalName); diff --git a/scripts/examples/location.qs b/scripts/examples/location.qs new file mode 100644 index 0000000..1ace32f --- /dev/null +++ b/scripts/examples/location.qs @@ -0,0 +1,20 @@ +// This script just moves continuasly from the current location to another one +// Interesting parts: +// location.latitude +// location.longitude +// location.altitude +// (current not working) location.datetime + +var i = 0; +while (i < 10) +{ + location.latitude += 0.0001; + location.longitude -= 0.0001; + location.altitude += 0.000001; + location.useCurrentTimestamp = true; + + print ("Updated position:" + i); + i = i + 1; + + yield(2000); +} diff --git a/scripts/examples/messagebox.qs b/scripts/examples/messagebox.qs new file mode 100644 index 0000000..1de34ae --- /dev/null +++ b/scripts/examples/messagebox.qs @@ -0,0 +1,3 @@ +// Simply show a message box + +messageBox("Message Boxes are always useful for debugging purposes"); diff --git a/scripts/examples/rotate.qs b/scripts/examples/rotate.qs new file mode 100644 index 0000000..605e129 --- /dev/null +++ b/scripts/examples/rotate.qs @@ -0,0 +1,2 @@ +// This example lets the simulator rotate +simulator.rotate(); diff --git a/scripts/examples/runOutOfBattery.qs b/scripts/examples/runOutOfBattery.qs new file mode 100644 index 0000000..124492c --- /dev/null +++ b/scripts/examples/runOutOfBattery.qs @@ -0,0 +1,18 @@ +// Decreases the battery level over 15 seconds until it's empty + +var startBatteryLevel = sysinfo.generic.batteryLevel; // save start battery level +var drainTime = 15; // seconds +var steps = 15; // number of steps for reducing battery level + +// set power state to battery power +sysinfo.generic.currentPowerState = sysinfo.generic.BatteryPower; + +// running this script doesn't make sense if battery is already drained +if (startBatteryLevel === 0) + startBatteryLevel = 100; + +// slowly drain battery +for (var i = 0; i < steps; ++i) { + sysinfo.generic.batteryLevel = startBatteryLevel * (1 - i/(steps-1)); + yield(drainTime/steps * 1000); +} diff --git a/scripts/examples/sysinfodevice.qs b/scripts/examples/sysinfodevice.qs new file mode 100644 index 0000000..7d8e331 --- /dev/null +++ b/scripts/examples/sysinfodevice.qs @@ -0,0 +1,11 @@ +// set some device data + +sysinfo.generic.batteryLevel = 11; +sysinfo.generic.currentPowerState = sysinfo.generic.WallPower; +sysinfo.generic.simStatus = sysinfo.generic.SimLocked; +sysinfo.generic.currentProfile = sysinfo.generic.LoudProfile; +sysinfo.generic.imsi = "543210987654321" +sysinfo.generic.imei = "54-321098-765432-1" +sysinfo.generic.deviceLocked = true; + + diff --git a/scripts/examples/sysinfogeneric.qs b/scripts/examples/sysinfogeneric.qs new file mode 100644 index 0000000..5cfccad --- /dev/null +++ b/scripts/examples/sysinfogeneric.qs @@ -0,0 +1,6 @@ +sysinfo.generic.currentLanguage = "bork" +sysinfo.generic.currentCountryCode = "Borkland" +sysinfo.generic.addAvailableLanguage("talk") +sysinfo.generic.setFeature(sysinfo.generic.BluetoothFeature, true) +sysinfo.generic.setVersion(sysinfo.generic.QtCore, "4.7") +print(sysinfo.generic.version(sysinfo.generic.QtCore)) diff --git a/scripts/examples/sysinfonetwork.qs b/scripts/examples/sysinfonetwork.qs new file mode 100644 index 0000000..97693ef --- /dev/null +++ b/scripts/examples/sysinfonetwork.qs @@ -0,0 +1,16 @@ +// set some network data + +sysinfo.network.currentMobileCountryCode = "fi"; + +sysinfo.network.cellId = 1; +sysinfo.network.setNetworkSignalStrength(sysinfo.network.GsmMode, 10); +yield(2000); +sysinfo.network.cellId = 2; +sysinfo.network.setNetworkSignalStrength(sysinfo.network.GsmMode, 50); +yield(2000); +sysinfo.network.cellId = 3; +sysinfo.network.setNetworkSignalStrength(sysinfo.network.GsmMode, 20); +yield(2000); +sysinfo.network.cellId = 4; +sysinfo.network.setNetworkSignalStrength(sysinfo.network.GsmMode, 100); +yield(2000) diff --git a/scripts/favorites/favoriteScript.qs b/scripts/favorites/favoriteScript.qs new file mode 100644 index 0000000..13cfc31 --- /dev/null +++ b/scripts/favorites/favoriteScript.qs @@ -0,0 +1 @@ +print("Put your favorite scripts into this folder."); diff --git a/simulator.pro b/simulator.pro new file mode 100644 index 0000000..c5afa42 --- /dev/null +++ b/simulator.pro @@ -0,0 +1,45 @@ +TEMPLATE = app + +# Grab paths from environment variables if unset +isEmpty(QT_NOKIA_SDK_PATH): QT_NOKIA_SDK_PATH = $$(QT_NOKIA_SDK_PATH) +isEmpty(QT_MOBILITY_SOURCE_PATH): QT_MOBILITY_SOURCE_PATH = $$(QT_MOBILITY_SOURCE_PATH) +isEmpty(QMF_INCLUDEDIR): QMF_INCLUDEDIR = $$(QMF_INCLUDEDIR) +isEmpty(SIMULATOR_DEPENDENCY_PATH): SIMULATOR_DEPENDENCY_PATH = $$(SIMULATOR_DEPENDENCY_PATH) + +isEmpty(QT_NOKIA_SDK_PATH): error(Please call qmake with QT_NOKIA_SDK_PATH=<path to nokia-sdk source directory>) +isEmpty(QT_MOBILITY_SOURCE_PATH): error(Please call qmake with QT_MOBILITY_SOURCE_PATH=<path to mobility source directory>) +isEmpty(QMF_INCLUDEDIR): error(Please call qmake with QMF_INCLUDEDIR=<qmf-source/src/libraries/qtopiamail>) +isEmpty(SIMULATOR_DEPENDENCY_PATH): error(Please call qmake with SIMULATOR_DEPENDENCY_PATH=<simulator-dependency-path>) + +TARGET = simulator +DESTDIR= ./ +QT += network +CONFIG += mobility +MOBILITY += contacts versit +contains(QT_CONFIG, phonon) { + QT += phonon +} + +include(src/src.pri) +include(doc/doc.pri) + +# install rules +!isEmpty(PREFIX) { + target.path = $$PREFIX + + macx: INSTALLSUBDIR=$${TARGET}.app/Contents/MacOS/ + + scripts.files = scripts + scripts.path = $$PREFIX/$$INSTALLSUBDIR + + stubdata.files = stubdata + stubdata.path = $$PREFIX/$$INSTALLSUBDIR + + fonts.files = fonts/*.ttf + fonts.path = $$PREFIX/$$INSTALLSUBDIR/fonts + + devices.files = models + devices.path = $$PREFIX/$$INSTALLSUBDIR + + INSTALLS += target scripts stubdata fonts devices +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..1bf669b --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,127 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtsingleapplication.h" + +#include "ui/mainwindow.h" +#include "qsimulatordata_p.h" +#include "messaging.h" + +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QSettings> +#include <QtCore/QTimer> +#include <QtGui/QApplication> +#include <QtGui/QDesktopServices> + +static void registerSimulator(const QString &location) +{ + QSettings userSettings; + QSettings *settings = &userSettings; +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) + // If the system settings are writable, don't touch the user settings. + // The reason is that a simulator started with sudo could otherwise create + // a root-owned configuration file a user directory. + QSettings systemSettings(QSettings::SystemScope, SIMULATOR_APP_VENDOR, SIMULATOR_APP_NAME); + + // QSettings::isWritable isn't reliable enough in 4.7, determine writability experimentally + systemSettings.setValue(SIMULATOR_APP_LOCATION_KEY, QLatin1String("SETTABLE")); + systemSettings.sync(); + if (systemSettings.status() == QSettings::NoError) { + settings = &systemSettings; + if (userSettings.contains(SIMULATOR_APP_LOCATION_KEY)) + userSettings.remove(SIMULATOR_APP_LOCATION_KEY); + } +#endif + + const QString locationKey = QLatin1String(SIMULATOR_APP_LOCATION_KEY); + QVariant value = settings->value(locationKey); + if (!value.isValid() || settings->value(locationKey).toString() != location) + settings->setValue(locationKey, location); + + const QString dataKey = QLatin1String(SIMULATOR_APP_DATA_KEY); + QString appDataLocation = QDesktopServices::storageLocation(QDesktopServices::DataLocation); + if (appDataLocation.isEmpty()) + appDataLocation = location; + + value = settings->value(dataKey); + if (!value.isValid() || settings->value(dataKey).toString() != appDataLocation) + settings->setValue(dataKey, appDataLocation); +} + +int main(int argc, char **argv) +{ + QCoreApplication::setOrganizationName(SIMULATOR_APP_VENDOR); + QCoreApplication::setApplicationName(SIMULATOR_APP_NAME); + + SharedTools::QtSingleApplication app(SIMULATOR_APP_NAME, argc, argv); + + QDir::setCurrent(app.applicationDirPath()); + + QDir pluginsDir = QDir::current(); + if (pluginsDir.cd("plugins")) + QApplication::addLibraryPath(pluginsDir.absolutePath()); + + registerSimulator(app.applicationFilePath()); + + if (argc >= 2 && QByteArray(argv[1]) == "-registeronly") { + //As creation of the messaging folder takes ages, we do that when + //registering the simulator + Messaging m; + m.setInitialData(); + // Don't return directly. Otherwise we crash. + QTimer::singleShot(1000, &app, SLOT(quit())); + return app.exec(); + } + + bool isFirstInstance = !app.isRunning(); + if (argc >= 3 && QByteArray(argv[1]) == "-runscript") { + if (isFirstInstance) { + qWarning() << "Ignored -runscript: No running simulator found"; + return -1; + } + + if (!app.sendMessage(QString("runscript %1").arg(argv[2]))) { + qWarning() << "Could not send message to running simulator."; + return -1; + } + } + + if (!isFirstInstance) { + // activate running instance? + return 0; + } + + app.initialize(); + MainWindow main; + QObject::connect(&app, SIGNAL(messageReceived(QString)), &main, SLOT(handleMessage(QString))); + main.show(); + return app.exec(); +} + diff --git a/src/mobility/contacts.cpp b/src/mobility/contacts.cpp new file mode 100644 index 0000000..fd5933c --- /dev/null +++ b/src/mobility/contacts.cpp @@ -0,0 +1,108 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "contacts.h" + +#include <contacts/qcontact.h> +#include <contacts/qcontactmanager.h> +#include <contacts/details/qcontactname.h> +#include <contacts/details/qcontactdisplaylabel.h> +#include <contacts/details/qcontactphonenumber.h> +#include <contacts/engines/qcontactmemorybackend_p.h> +#include <versit/qversitreader.h> +#include <versit/qversitcontactimporter.h> + +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QFile> +#include <QtCore/QTextStream> + +using namespace QtMobility; + +Contacts::Contacts(QObject *parent) + : QObject(parent) +{ + QMap<QString, QString> engineParams; + engineParams.insert("id", "simulator"); + mManager = new QContactManager("memory", engineParams, this); + + connect(mManager, SIGNAL(contactsAdded(const QList<QContactLocalId> &)), SIGNAL(contactsAdded(const QList<QContactLocalId> &))); + connect(mManager, SIGNAL(contactsChanged(const QList<QContactLocalId> &)), SIGNAL(contactsChanged(const QList<QContactLocalId> &))); + connect(mManager, SIGNAL(contactsRemoved(const QList<QContactLocalId> &)), SIGNAL(contactsRemoved(const QList<QContactLocalId> &))); + connect(mManager, SIGNAL(relationshipsAdded(QList<QContactLocalId>)), SIGNAL(relationshipsAdded(QList<QContactLocalId>))); + connect(mManager, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)), SIGNAL(relationshipsRemoved(QList<QContactLocalId>))); +} + +QContactManager *Contacts::manager() +{ + return mManager; +} + +void Contacts::setInitialData() +{ + importFromVCardFile("stubdata/standardselfcontact.vcf"); + if (mManager->contactIds().count() == 1) { + mManager->setSelfContactId(mManager->contactIds().at(0)); + } else { + qWarning("The file stubdata/standardselfcontact.vcf contains more than one contact. Not setting a self contact."); + } + + importFromVCardFile("stubdata/standardcontacts.vcf"); +} + +void Contacts::publish() const +{ + emit contactsDataChanged(*mManager); +} + +bool Contacts::importFromVCardFile(const QString &fileName) +{ + QFile contactsFile(fileName); + contactsFile.open(QIODevice::ReadOnly); + if (!contactsFile.isReadable()) + return false; + + QVersitReader reader; + reader.setDevice(&contactsFile); + if (!reader.startReading()) + return false; + reader.waitForFinished(); + + QVersitContactImporter importer; + if (!importer.importDocuments(reader.results())) { + qWarning() << "Could not import contacts from " << fileName; + return false; + } + + QList<QContact> contacts = importer.contacts(); + QMap<int, QContactManager::Error> errors; + mManager->saveContacts(&contacts, &errors); + + return true; +} diff --git a/src/mobility/contacts.h b/src/mobility/contacts.h new file mode 100644 index 0000000..7f18b51 --- /dev/null +++ b/src/mobility/contacts.h @@ -0,0 +1,75 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CONTACTS_H +#define CONTACTS_H + +#include <QtCore/QObject> +#include <QtCore/QList> +#include <contacts/qtcontactsglobal.h> + +namespace QtMobility { + class QContactManager; +} + +// These are required - otherwise the signals defined below have to contain +// QtMobility:: in their signature and and that makes connect() refuse to +// connect them. +using QtMobility::QContactLocalId; +using QtMobility::QContactManager; + +class Contacts : public QObject +{ + Q_OBJECT +public: + explicit Contacts(QObject *parent = 0); + + QtMobility::QContactManager *manager(); + +public slots: + void setInitialData(); + void publish() const; + bool importFromVCardFile(const QString &fileName); + +signals: + // for incremental changes triggered remotely + void contactsAdded(const QList<QContactLocalId> &contactIds) const; + void contactsChanged(const QList<QContactLocalId> &contactIds) const; + void contactsRemoved(const QList<QContactLocalId> &contactIds) const; + void relationshipsAdded(const QList<QContactLocalId> &affectedContactIds) const; + void relationshipsRemoved(const QList<QContactLocalId> &affectedContactIds) const; + + // for a complete update triggered by publish + void contactsDataChanged(const QContactManager &) const; + +private: + QtMobility::QContactManager *mManager; +}; + +#endif // CONTACTS_H diff --git a/src/mobility/messaging.cpp b/src/mobility/messaging.cpp new file mode 100644 index 0000000..00eadc9 --- /dev/null +++ b/src/mobility/messaging.cpp @@ -0,0 +1,149 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "messaging.h" + +#include <qmailstore.h> +#include <qsimulatordata_p.h> + +#include <QtCore/QDir> +#include <QtCore/QThread> + +class MaildirImporter : public QThread +{ +public: + MaildirImporter(const QString &path, QObject *parent = 0) + : QThread(parent), mPath(path) + { + } + +protected: + virtual void run() + { + QDir dir(mPath); + if (!dir.exists()) + return; + + QMailStore *store = QMailStore::instance(); + QMailAccountIdList accountIdList = store->queryAccounts(); + if (accountIdList.isEmpty()) + return; + QMailFolderIdList folderIdList = store->queryFolders(); + if (folderIdList.isEmpty()) + return; + + foreach (const QFileInfo &fileInfo, dir.entryInfoList(QDir::Files)) { + QFile file(fileInfo.absoluteFilePath()); + file.open(QIODevice::ReadOnly); + QByteArray data = file.readAll(); + file.close(); + + // RFC 2822 requires CRLF line endings + for (int i = 0; i < data.size(); ++i) { + if (data.at(i) == '\n' && i > 0 && data.at(i-1) != '\r') { + data.insert(i, '\r'); + ++i; + } + } + + QMailMessage message(QMailMessage::fromRfc2822(data)); + if (message.headerFields().isEmpty()) + continue; + + QMailMessage *storeMessage = new QMailMessage(message); + storeMessage->setMessageType(QMailMessage::Email); + storeMessage->setParentAccountId(accountIdList.first()); + storeMessage->setParentFolderId(folderIdList.first()); + QMailStore::instance()->addMessage(storeMessage); + } + } + +private: + QString mPath; +}; + +Messaging::Messaging(QObject *parent) : + QObject(parent) +{ +} + +void Messaging::setInitialData() +{ + // have to use the same on the client + QtSimulatorPrivate::qt_setQmfPaths(); + + QMailStore *mailstore = QMailStore::instance(); + + // remove existing data + mailstore->removeAccounts(QMailAccountKey()); + + // add stub account + QMailAccount *account = new QMailAccount(); + account->setName("TestAccount"); + mailstore->addAccount(account, 0); + + // add stub folder + QMailFolder *folder = new QMailFolder("TestFolder"); + mailstore->addFolder(folder); + + importMaildir("stubdata/standardmessages"); +} + +void Messaging::addMessage(QMailMessage *message) +{ + QMailStore *store = QMailStore::instance(); + QMailAccountIdList accountIdList = store->queryAccounts(); + if (accountIdList.isEmpty()) + return; + QMailFolderIdList folderIdList = store->queryFolders(); + if (folderIdList.isEmpty()) + return; + + message->setParentAccountId(accountIdList.first()); + message->setParentFolderId(folderIdList.first()); + store->addMessage(message); +} + +void Messaging::importMaildir(const QString &path) +{ + // remove done threads + QMutableListIterator<MaildirImporter *> it(mImporterThreads); + while (it.hasNext()) { + MaildirImporter *importer = it.next(); + if (importer->isFinished()) { + delete importer; + it.remove(); + } + } + + // start new importer thread + MaildirImporter *maildirImporter = new MaildirImporter(path, this); + maildirImporter->start(); + mImporterThreads += maildirImporter; +} diff --git a/src/mobility/messaging.h b/src/mobility/messaging.h new file mode 100644 index 0000000..1cbf54d --- /dev/null +++ b/src/mobility/messaging.h @@ -0,0 +1,56 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MESSAGING_H +#define MESSAGING_H + +#include <QtCore/QObject> + +class MaildirImporter; +class QMailAccount; +class QMailFolder; +class QMailMessage; + +class Messaging : public QObject +{ +Q_OBJECT +public: + explicit Messaging(QObject *parent = 0); + + void importMaildir(const QString &path); + void addMessage(QMailMessage *message); + +public slots: + void setInitialData(); + +private: + QList<MaildirImporter *> mImporterThreads; +}; + +#endif // MESSAGING_H diff --git a/src/mobility/mobility.pri b/src/mobility/mobility.pri new file mode 100644 index 0000000..86c81a7 --- /dev/null +++ b/src/mobility/mobility.pri @@ -0,0 +1,12 @@ +INCLUDEPATH += src/mobility +DEPENDPATH += src/mobility +SOURCES += \ + mobilitymanager.cpp \ + contacts.cpp \ + mobilitydata.cpp \ + messaging.cpp +HEADERS += \ + mobilitymanager.h \ + contacts.h \ + mobilitydata.h \ + messaging.h diff --git a/src/mobility/mobilitydata.cpp b/src/mobility/mobilitydata.cpp new file mode 100644 index 0000000..469a409 --- /dev/null +++ b/src/mobility/mobilitydata.cpp @@ -0,0 +1,262 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mobilitydata.h" + +#include <contacts/qcontactmanager.h> +#include <contacts/qcontact.h> +#include <contacts/details/qcontactemailaddress.h> +#include <contacts/details/qcontactphonenumber.h> +#include <qmailmessage.h> + +#include <qmath.h> + +using namespace QtMobility; + +MobilityData::MobilityData(QObject *parent) + : QObject(parent) + , mContacts(new Contacts(this)) + , mLocationUi(0) + , mSystemInfoGenericUi(0) + , mSystemInfoNetworkUi(0) + , mSystemInfoStorageUi(0) + , mMessaging(new Messaging(this)) + , mSensorsUi(0) + , mInitialized(false) + , mInitializeWithLandscape(false) +{ +} + +void MobilityData::setInitialData() +{ + setInitialLocationData(); + mContacts->setInitialData(); + setInitialSystemInfoGenericData(); + setInitialSystemInfoNetworkData(); + setInitialSystemInfoStorageData(); + mMessaging->setInitialData(); + setInitialSensorsData(); +} + +void MobilityData::setInitialSensorsData() +{ + SensorsUi::SensorsData sensors; + sensors.ambientLightLevel = SensorsScriptInterface::Light; + + if (mInitializeWithLandscape) { + sensors.accelerometerX = -9.8; + sensors.accelerometerY = 0; + } else { + sensors.accelerometerX = 0; + sensors.accelerometerY = 9.8; + } + sensors.accelerometerZ = 0; + + sensors.magnetometerX = 0.5; + sensors.magnetometerY = 0.5; + sensors.magnetometerY = 0.5; + sensors.magnetometerCalibrationLevel = 0.85; + + sensors.compassCalibrationLevel = 0.85; + sensors.compassAzimuth = 132.65; + + sensors.proximitySensorClose = true; + + mSensorsUi->setSensorsData(sensors); + mInitialized = true; +} + +void MobilityData::setInitialLocationData() +{ + LocationUi::LocationData data; + data.latitude = 52.5056819; + data.longitude = 13.3232027; + data.altitude = 4.897392; + data.useCurrentTime = true; + mLocationUi->setLocation(data); +} + +void MobilityData::setInitialSystemInfoGenericData() +{ + GenericSystemInfoUi::GenericData data; + data.currentLanguage = "en"; + data.currentCountryCode = "EN"; + data.availableLanguages.append("en"); + data.availableLanguages.append("de"); + data.features[GenericSystemInfoScriptInterface::LocationFeature] = true; + data.features[GenericSystemInfoScriptInterface::UsbFeature] = true; + data.versions[GenericSystemInfoScriptInterface::QtCore] = "4.6 probably"; + data.versions[GenericSystemInfoScriptInterface::Firmware] = "1.9-alpha-rc7"; + data.displayBrightness = 100; + data.colorDepth = 32; + data.profile = GenericSystemInfoScriptInterface::NormalProfile; + data.currentPowerState = GenericSystemInfoScriptInterface::WallPower; + data.simStatus = GenericSystemInfoScriptInterface::SimNotAvailable; + data.inputFlags = static_cast<GenericSystemInfoScriptInterface::InputMethod> + (GenericSystemInfoScriptInterface::Keyboard | GenericSystemInfoScriptInterface::Mouse); + data.imei = "12-345678-901234-5"; + data.imsi = "12345679012345"; + data.manufacturer = "simulator manufacturer"; + data.model = "simulator model"; + data.productName = "simulator product name"; + data.batteryLevel = 84; + data.deviceLocked = false; + mSystemInfoGenericUi->setGenericData(data); +} + +void MobilityData::setInitialSystemInfoNetworkData() +{ + NetworkSystemInfoUi::NetworkData data; + data.cellId = 12345; + data.locationAreaCode = 54321; + data.currentMobileCountryCode = QLatin1String("242"); + data.currentMobileNetworkCode = QLatin1String("123456789"); + data.homeMobileCountryCode = QLatin1String("+47"); + data.homeMobileNetworkCode = QLatin1String("987654321"); + data.currentMode = NetworkSystemInfoScriptInterface::EthernetMode; + + for (int i = 0; i < data.networkInfo.size(); ++i) { + NetworkSystemInfoUi::NetworkData::ModeInfo &mode = data.networkInfo[i]; + + mode.name = QLatin1String("name"); + mode.macAddress = QLatin1String("ff:ff:ff:ff:ff:ff"); + mode.signalStrength = 75; + mode.status = NetworkSystemInfoScriptInterface::UndefinedStatus; + } + mSystemInfoNetworkUi->setNetworkData(data); +} + +void MobilityData::setInitialSystemInfoStorageData() +{ + StorageSystemInfoScriptInterface *si = mSystemInfoStorageUi->scriptInterface(); + si->addDrive("Internal Drive", StorageSystemInfoScriptInterface::InternalDrive, + 256*1024*qint64(1024), 32*1024*qint64(1024)); + si->addDrive("Removable Drive", StorageSystemInfoScriptInterface::RemovableDrive, + 4*1024*1024*qint64(1024), 3*1024*1024*qint64(1024)); +} + +static int randomInt(int begin, int end) +{ + return begin + floor((qreal)qrand() / RAND_MAX * (end - begin)); +} + +void MobilityData::addNewEmail() +{ + // ### A script should do this... + QContactManager *manager = mContacts->manager(); + + // find sender + QList<QContact> contacts = manager->contacts(); + QContact sender = contacts.at(randomInt(0, contacts.size())); + + // find target + QContact receiver = manager->contact(manager->selfContactId()); + + // make message + QMailMessage *message = new QMailMessage(); + message->setMessageType(QMailMessage::Email); + message->setSubject(tr("Generated message")); + message->setBody( + QMailMessageBody::fromData(tr("This is a simulator-generated email message."), + QMailMessageContentType("text/plain"), + QMailMessageBodyFwd::NoEncoding)); + message->setFrom(QMailAddress(sender.displayLabel(), + sender.detail<QContactEmailAddress>().emailAddress())); + message->setTo(QMailAddress(receiver.displayLabel(), + receiver.detail<QContactEmailAddress>().emailAddress())); + mMessaging->addMessage(message); +} + +void MobilityData::addNewSms() +{ + // ### A script should do this... + QContactManager *manager = mContacts->manager(); + + // find sender + QList<QContact> contacts = manager->contacts(); + QContact sender = contacts.at(randomInt(0, contacts.size())); + + // find target + QContact receiver = manager->contact(manager->selfContactId()); + + // make message + QMailMessage *message = new QMailMessage(); + message->setMessageType(QMailMessage::Sms); + message->setSubject(tr("Generated message")); + message->setBody( + QMailMessageBody::fromData(tr("This is a simulator-generated SMS message."), + QMailMessageContentType("text/plain"), + QMailMessageBodyFwd::NoEncoding)); + message->setFrom(QMailAddress(sender.displayLabel(), + sender.detail<QContactPhoneNumber>().number())); + message->setTo(QMailAddress(receiver.displayLabel(), + receiver.detail<QContactPhoneNumber>().number())); + mMessaging->addMessage(message); +} + +void MobilityData::rotateDevice(Orientation current, Orientation native) +{ + SensorsUi::SensorsData sensors = mSensorsUi->sensorsData(); + + if (native == landscapeOrientation) { + if (current == portraitOrientation) { + sensors.accelerometerX -= 9.8; + sensors.accelerometerY -= 9.8; + } else { + sensors.accelerometerX += 9.8; + sensors.accelerometerY += 9.8; + } + } else { + if (current == portraitOrientation) { + sensors.accelerometerX -= 9.8; + sensors.accelerometerY += 9.8; + } else { + sensors.accelerometerX += 9.8; + sensors.accelerometerY -= 9.8; + } + } + + mSensorsUi->setSensorsData(sensors); +} + +void MobilityData::changeDevice(Orientation current, Orientation currentNative, Orientation targetNative) +{ + if (currentNative == targetNative) + return; + + if (!mInitialized) { + if (targetNative == landscapeOrientation) + mInitializeWithLandscape = true; + else + mInitializeWithLandscape = false; + return; + } + + rotateDevice(currentNative, current == landscapeOrientation ? portraitOrientation : landscapeOrientation); +} diff --git a/src/mobility/mobilitydata.h b/src/mobility/mobilitydata.h new file mode 100644 index 0000000..4be7c98 --- /dev/null +++ b/src/mobility/mobilitydata.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MOBILITYDATA_H +#define MOBILITYDATA_H + +#include <QObject> + +// while a forward declaration would suffice, we include these here +// as everything using MobilityData will usually want to include them too +#include "contacts.h" +#include "systeminfogenericui.h" +#include "systeminfonetworkui.h" +#include "systeminfostorageui.h" +#include "messaging.h" +#include "sensorsui.h" +#include "deviceitem.h" + +#include <remotecontrolwidget/locationui.h> + +class MobilityData : public QObject +{ +Q_OBJECT +public: + explicit MobilityData(QObject *parent = 0); + + Contacts *mContacts; + LocationUi *mLocationUi; + GenericSystemInfoUi *mSystemInfoGenericUi; + NetworkSystemInfoUi *mSystemInfoNetworkUi; + StorageSystemInfoUi *mSystemInfoStorageUi; + Messaging *mMessaging; + SensorsUi *mSensorsUi; + + void setInitialData(); + +public slots: + void addNewEmail(); + void addNewSms(); + + // for adjusting data based on orientation of device + void rotateDevice(Orientation current, Orientation native); + void changeDevice(Orientation current, Orientation currentNative, Orientation targetNative); + +private: + void setInitialSensorsData(); + void setInitialLocationData(); + void setInitialSystemInfoNetworkData(); + void setInitialSystemInfoStorageData(); + void setInitialSystemInfoGenericData(); + + bool mInitialized; + bool mInitializeWithLandscape; +}; + +#endif // MOBILITYDATA_H diff --git a/src/mobility/mobilitymanager.cpp b/src/mobility/mobilitymanager.cpp new file mode 100644 index 0000000..2bb340d --- /dev/null +++ b/src/mobility/mobilitymanager.cpp @@ -0,0 +1,503 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mobilitymanager.h" +#include "mobilitydata.h" + +#include <qsimulatordata_p.h> +#include <contacts/engines/qcontactmemorybackend_p.h> +#include <contacts/engines/qcontactmemorybackenddata_simulator_p.h> +#include <contacts/qcontactmanager.h> +#include <contacts/qcontactmanager_p.h> +#include <contacts/qcontactrelationship.h> + +#include <QtCore/QList> +#include <QtCore/QDebug> + +#include <QtNetwork/QLocalSocket> +#include <QtNetwork/QLocalServer> + +#include <limits> + +using namespace QtMobility; + +int MobilityClient::contactsClientsCount = 0; + +MobilityServer::MobilityServer(MobilityData *mobility, QObject *parent) + : QObject(parent) + , mMobility(mobility) +{ + mServer = new QLocalServer(); + QLocalServer::removeServer(SIMULATOR_MOBILITY_SERVERNAME); + if (!mServer->listen(SIMULATOR_MOBILITY_SERVERNAME)) { + qFatal("Could not open mobility server"); + } + connect(mServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + + qt_registerSystemInfoTypes(); + qt_registerContactsTypes(); + qt_registerLocationTypes(); + qt_registerSensorTypes(); +} + +MobilityServer::~MobilityServer() +{ + if (mServer) { + mServer->close(); + QLocalServer::removeServer(SIMULATOR_DISPLAY_SERVERNAME); + delete mServer; + mServer = 0; + } +} + +void MobilityServer::newConnection() +{ + // get the incoming connection + QLocalSocket* socket = mServer->nextPendingConnection(); + if (!socket->isValid()) { + qWarning() << "Invalid socket!"; + return; + } + + // expect an initial application connect packet to to verify that this is + // indeed a simulator client application and to get its pid + using namespace ::QtSimulatorPrivate; + + // read the command id + qint32 requestCommand = 0; + qint64 bytesToRead = sizeof(requestCommand); + qint64 bytesRead = qt_blockingRead( + socket, reinterpret_cast<char *>(&requestCommand), bytesToRead, 500); + if (bytesRead < bytesToRead) + { + qWarning("Dropped incoming connection, couldn't read command id."); + return; + } + if (requestCommand != QtSimulatorPrivate::Command::ApplicationConnect) + { + qWarning("Dropped incoming connection, it sent an invalid command."); + return; + } + + // read the command + QtSimulatorPrivate::ApplicationConnectCommand cmd; + bytesToRead = sizeof(cmd.request); + bytesRead = qt_blockingRead( + socket, reinterpret_cast<char *>(&cmd.request), bytesToRead, 500); + if (bytesRead < bytesToRead) + { + qWarning("Dropped incoming connection, couldn't read command data."); + return; + } + + // send a reply + qint64 bytesToWrite = sizeof(cmd.reply); + qint64 bytesWritten = qt_blockingWrite( + socket, reinterpret_cast<const char *>(&cmd.reply), bytesToWrite, 500); + if (bytesWritten < bytesToWrite) + { + qWarning("Dropped incoming connection, couldn't send connect reply."); + return; + } + + // success: register client + mClients.append(new MobilityClient(cmd.request.applicationPid, socket, this)); +} + +void MobilityServer::removeClient(MobilityClient *c) +{ + mClients.removeAll(c); +} + +MobilityClient::MobilityClient(qint64 pid, QLocalSocket *receiveSocket, MobilityServer *server) + : QObject(server) + , mPid(pid) + , mReceiveSocket(receiveSocket) + , mSendSocket(0) + , mMobilityServer(server) + , mNotifyClientOnContactsChange(true) +{ + // initiate sendSocket as a backchannel to the client + mSendSocket = new QLocalSocket(this); + mSendSocket->connectToServer(qt_mobilityServerName(pid)); + if (!mSendSocket->waitForConnected(1000)) + qFatal("Couldn't set up back channel to mobility interface of client"); + + // there might be data available already + readyRead(); + connect(mReceiveSocket, SIGNAL(readyRead()), this, SLOT(readyRead())); + connect(mReceiveSocket, SIGNAL(disconnected()), this, SLOT(disconnect())); +} + +MobilityClient::~MobilityClient() +{ + mSendSocket->disconnectFromServer(); + mSendSocket->deleteLater(); +} + +void MobilityClient::disconnect() +{ + mMobilityServer->removeClient(this); + delete this; +} + +void MobilityClient::readyRead() +{ + mReadBuffer += mReceiveSocket->readAll(); + forever { + QtSimulatorPrivate::IncomingRemoteMetacall rpc; + if (rpc.read(&mReadBuffer)) { + if (rpc.call(mReceiveSocket, this)) { + continue; + } + qWarning("Ignoring a call to %s, No such slot in MobilityClient.", rpc.signature().data()); + } + break; + } +} + +void MobilityClient::sendSystemGenericInfo(const GenericSystemInfoUi::GenericData &data) +{ + QSystemInfoData sysInfoData; + sysInfoData.availableLanguages = data.availableLanguages; + sysInfoData.currentCountryCode = data.currentCountryCode; + sysInfoData.currentLanguage = data.currentLanguage; + sysInfoData.features = data.features; + sysInfoData.versions = data.versions; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setSystemInfoData", sysInfoData); + QSystemDeviceInfoData deviceInfoData; + deviceInfoData.batteryLevel = data.batteryLevel; + deviceInfoData.currentPowerState = static_cast<QtMobility::QSystemDeviceInfo::PowerState>(data.currentPowerState); + deviceInfoData.currentProfile = static_cast<QtMobility::QSystemDeviceInfo::Profile>(data.profile); + deviceInfoData.deviceLocked = data.deviceLocked; + deviceInfoData.imei = data.imei; + deviceInfoData.imsi = data.imsi; + QtMobility::QSystemDeviceInfo::InputMethodFlags flags; + if (data.inputFlags & GenericSystemInfoScriptInterface::Keys) + flags |= QSystemDeviceInfo::Keys; + if (data.inputFlags & GenericSystemInfoScriptInterface::Keypad) + flags |= QSystemDeviceInfo::Keypad; + if (data.inputFlags & GenericSystemInfoScriptInterface::Keyboard) + flags |= QSystemDeviceInfo::Keyboard; + if (data.inputFlags & GenericSystemInfoScriptInterface::MultiTouch) + flags |= QSystemDeviceInfo::MultiTouch; + if (data.inputFlags & GenericSystemInfoScriptInterface::SingleTouch) + flags |= QSystemDeviceInfo::SingleTouch; + if (data.inputFlags & GenericSystemInfoScriptInterface::Mouse) + flags |= QSystemDeviceInfo::Mouse; + deviceInfoData.inputMethodType = flags; + deviceInfoData.manufacturer = data.manufacturer; + deviceInfoData.model = data.model; + deviceInfoData.productName = data.productName; + deviceInfoData.simStatus = static_cast<QtMobility::QSystemDeviceInfo::SimStatus>(data.simStatus); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setSystemDeviceInfoData", deviceInfoData); + + QSystemDisplayInfoData displayInfoData; + displayInfoData.colorDepth = data.colorDepth; + displayInfoData.displayBrightness = data.displayBrightness; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setSystemDisplayInfoData", displayInfoData); + +} + +void MobilityClient::sendSystemStorageInfo(const StorageSystemInfoUi::StorageData &data) +{ + QSystemStorageInfoData storage; + QHashIterator<QString, StorageSystemInfoUi::StorageData::DriveInfo> iter(data.drives); + while (iter.hasNext()) { + iter.next(); + QSystemStorageInfoData::DriveInfo info; + info.type = static_cast<QSystemStorageInfo::DriveType>(iter.value().type); + info.availableSpace = iter.value().availableSpace; + info.totalSpace = iter.value().totalSpace; + storage.drives.insert(iter.key(), info); + } + + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setSystemStorageInfoData", storage); +} + +void MobilityClient::sendSystemNetworkInfo(const NetworkSystemInfoUi::NetworkData &data) +{ + QSystemNetworkInfoData network; + network.cellId = data.cellId; + network.locationAreaCode = data.locationAreaCode; + network.currentMobileCountryCode = data.currentMobileCountryCode; + network.currentMobileNetworkCode = data.currentMobileNetworkCode; + network.homeMobileCountryCode = data.homeMobileCountryCode; + network.homeMobileNetworkCode = data.homeMobileNetworkCode; + network.currentMode = static_cast<QSystemNetworkInfo::NetworkMode>(data.currentMode); + foreach (const NetworkSystemInfoUi::NetworkData::ModeInfo &modeInfo, data.networkInfo) { + QSystemNetworkInfoData::NetworkInfo info; + info.name = modeInfo.name; + info.macAddress = modeInfo.macAddress; + info.signalStrength = modeInfo.signalStrength; + info.status = static_cast<QSystemNetworkInfo::NetworkStatus>(modeInfo.status); + network.networkInfo.append(info); + } + + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setSystemNetworkInfoData", network); +} + +void MobilityClient::sendLocationData(const LocationUi::LocationData &data) +{ + QGeoPositionInfoData location; + location.latitude = data.latitude; + location.longitude = data.longitude; + location.altitude = data.altitude; + if (data.useCurrentTime) + location.dateTime = QDateTime(); + else + location.dateTime = data.timestamp; + location.minimumInterval = 1000; + location.enabled = true; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setLocationData", location); +} + +void MobilityClient::sendSensorsData(const SensorsUi::SensorsData &data) +{ + QDateTime timestampToSend; + if (!data.useCurrentTime) + timestampToSend = data.timestamp; + QAmbientLightReadingData ambientData; + ambientData.lightLevel = static_cast<QtMobility::QAmbientLightReading::LightLevel>(data.ambientLightLevel); + ambientData.timestamp = timestampToSend; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setAmbientLightData", ambientData); + + QAccelerometerReadingData accelermometerData; + accelermometerData.x = data.accelerometerX; + accelermometerData.y = data.accelerometerY; + accelermometerData.z = data.accelerometerZ; + accelermometerData.timestamp = timestampToSend; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setAccelerometerData", accelermometerData); + + QMagnetometerReadingData magnetometerData; + magnetometerData.x = data.magnetometerX; + magnetometerData.y = data.magnetometerY; + magnetometerData.z = data.magnetometerZ; + magnetometerData.calibrationLevel = data.magnetometerCalibrationLevel; + magnetometerData.timestamp = timestampToSend; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setMagnetometerData", magnetometerData); + + QCompassReadingData compassData; + compassData.azimuth = data.compassAzimuth; + compassData.calibrationLevel = data.compassCalibrationLevel; + compassData.timestamp = timestampToSend; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setCompassData", compassData); + + QProximityReadingData proximityData; + proximityData.close = data.proximitySensorClose; + proximityData.timestamp = timestampToSend; + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setProximityData", proximityData); +} + +// Sends simulator contact data to client, overwriting its local data. +// Can invalidate ids the client stored locally. +// Ideally it's used only for the initial data transmission. +void MobilityClient::sendContactData(const QContactManager &manager) +{ + QContactSimulatorData data; + QContactMemoryEngineData *engineData = static_cast<QContactMemoryEngine *>(manager.d->m_engine)->d; + data.m_selfContactId = engineData->m_selfContactId; + data.m_contacts = engineData->m_contacts; + data.m_contactIds = engineData->m_contactIds; + data.m_relationships = engineData->m_relationships; + data.m_orderedRelationships = engineData->m_orderedRelationships; + data.m_definitionIds = engineData->m_definitionIds; + data.m_definitions = engineData->m_definitions; + data.m_nextContactId = engineData->m_nextContactId; + + // to avoid collisions, give each client a large area for unique detail ids + // ### TODO: Ugly hack. + contactsClientsCount++; + data.m_lastDetailId = std::numeric_limits<int>::max() / 1000 * contactsClientsCount; + + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setContactData", data); +} + +void MobilityClient::setRequestsSystemInfo() +{ + connect(mMobilityServer->mMobility->mSystemInfoStorageUi, SIGNAL(storageDataChanged(StorageSystemInfoUi::StorageData)), + SLOT(sendSystemStorageInfo(StorageSystemInfoUi::StorageData))); + connect(mMobilityServer->mMobility->mSystemInfoGenericUi, SIGNAL(genericDataChanged(GenericSystemInfoUi::GenericData)), + SLOT(sendSystemGenericInfo(GenericSystemInfoUi::GenericData))); + connect(mMobilityServer->mMobility->mSystemInfoNetworkUi, SIGNAL(networkDataChanged(NetworkSystemInfoUi::NetworkData)), + SLOT(sendSystemNetworkInfo(NetworkSystemInfoUi::NetworkData))); + sendSystemGenericInfo(mMobilityServer->mMobility->mSystemInfoGenericUi->genericData()); + sendSystemNetworkInfo(mMobilityServer->mMobility->mSystemInfoNetworkUi->networkData()); + sendSystemStorageInfo(mMobilityServer->mMobility->mSystemInfoStorageUi->storageData()); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "initialSystemInfoDataSent"); +} + +void MobilityClient::setRequestsLocationInfo() +{ + connect(mMobilityServer->mMobility->mLocationUi, SIGNAL(locationChanged(LocationUi::LocationData)), + SLOT(sendLocationData(LocationUi::LocationData))); + sendLocationData(mMobilityServer->mMobility->mLocationUi->locationData()); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "initialLocationDataSent"); +} + +void MobilityClient::setRequestsContactInfo() +{ + connect(mMobilityServer->mMobility->mContacts, SIGNAL(contactsDataChanged(QContactManager)), this, SLOT(sendContactData(QContactManager))); + connect(mMobilityServer->mMobility->mContacts, SIGNAL(contactsAdded(QList<QContactLocalId>)), this, SLOT(sendAddedContacts(QList<QContactLocalId>))); + connect(mMobilityServer->mMobility->mContacts, SIGNAL(contactsChanged(QList<QContactLocalId>)), this, SLOT(sendChangedContacts(QList<QContactLocalId>))); + connect(mMobilityServer->mMobility->mContacts, SIGNAL(contactsRemoved(QList<QContactLocalId>)), this, SLOT(sendRemovedContacts(QList<QContactLocalId>))); + connect(mMobilityServer->mMobility->mContacts, SIGNAL(relationshipsAdded(QList<QContactLocalId>)), this, SLOT(sendRelationshipsFor(QList<QContactLocalId>))); + connect(mMobilityServer->mMobility->mContacts, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)), this, SLOT(sendRelationshipsFor(QList<QContactLocalId>))); +} + +void MobilityClient::setRequestsSensors() +{ + connect(mMobilityServer->mMobility->mSensorsUi, SIGNAL(sensorsDataChanged(SensorsUi::SensorsData)), + SLOT(sendSensorsData(SensorsUi::SensorsData))); + sendSensorsData(mMobilityServer->mMobility->mSensorsUi->sensorsData()); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "initialSensorsDataSent"); +} + +void MobilityClient::triggerContactDataResend() +{ + mMobilityServer->mMobility->mContacts->publish(); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "initialContactDataSent"); +} + +Simulator::SaveContactReply MobilityClient::requestSaveContact(const QContact &contact) +{ + Simulator::SaveContactReply reply; + reply.savedContact = contact; + + // execute change and notify other clients in the process + mNotifyClientOnContactsChange = false; + mMobilityServer->mMobility->mContacts->manager()->saveContact(&reply.savedContact); + mNotifyClientOnContactsChange = true; + + reply.error = mMobilityServer->mMobility->mContacts->manager()->error(); + return reply; +} + +int MobilityClient::requestRemoveContact(uint id) +{ + // execute change and notify other clients in the process + mNotifyClientOnContactsChange = false; + mMobilityServer->mMobility->mContacts->manager()->removeContact(id); + mNotifyClientOnContactsChange = true; + + return static_cast<int>(mMobilityServer->mMobility->mContacts->manager()->error()); +} + +Simulator::SaveRelationshipReply MobilityClient::requestSaveRelationship(const QContactRelationship &relationship) +{ + Simulator::SaveRelationshipReply reply; + reply.savedRelationship = relationship; + + // execute change and notify other clients in the process + mNotifyClientOnContactsChange = false; + mMobilityServer->mMobility->mContacts->manager()->saveRelationship(&reply.savedRelationship); + mNotifyClientOnContactsChange = true; + + reply.error = mMobilityServer->mMobility->mContacts->manager()->error(); + return reply; +} + +int MobilityClient::requestRemoveRelationship(const QContactRelationship &relationship) +{ + // execute change and notify other clients in the process + mNotifyClientOnContactsChange = false; + mMobilityServer->mMobility->mContacts->manager()->removeRelationship(relationship); + mNotifyClientOnContactsChange = true; + + return static_cast<int>(mMobilityServer->mMobility->mContacts->manager()->error()); +} + +void MobilityClient::sendAddedContacts(const QList<QContactLocalId> &contactIds) +{ + if (!mNotifyClientOnContactsChange) + return; + + foreach (QContactLocalId id, contactIds) { + const QContact &contact = mMobilityServer->mMobility->mContacts->manager()->contact(id); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "addContact", contact); + } +} + +void MobilityClient::sendChangedContacts(const QList<QContactLocalId> &contactIds) +{ + if (!mNotifyClientOnContactsChange) + return; + + foreach (QContactLocalId id, contactIds) { + const QContact &contact = mMobilityServer->mMobility->mContacts->manager()->contact(id); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "changeContact", contact); + } +} + +void MobilityClient::sendRemovedContacts(const QList<QContactLocalId> &contactIds) +{ + if (!mNotifyClientOnContactsChange) + return; + + foreach (QContactLocalId id, contactIds) { + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "removeContact", id); + } +} + +void MobilityClient::sendRelationshipsFor(const QList<QContactLocalId> &contactIds) +{ + if (!mNotifyClientOnContactsChange) + return; + + QContactManager *manager = mMobilityServer->mMobility->mContacts->manager(); + + foreach (QContactLocalId localId, contactIds) { + QContactId id(manager->contact(localId).id()); + QList<QContactRelationship> relationships(manager->relationships(id)); + QVariantList list; + foreach (const QContactRelationship &r, relationships) + list.append(QVariant::fromValue(r)); + QtSimulatorPrivate::RemoteMetacall<void>::call(mSendSocket, QtSimulatorPrivate::NoSync, + "setRelationships", localId, list); + } +} diff --git a/src/mobility/mobilitymanager.h b/src/mobility/mobilitymanager.h new file mode 100644 index 0000000..0888f3d --- /dev/null +++ b/src/mobility/mobilitymanager.h @@ -0,0 +1,130 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MOBILITY_H +#define MOBILITY_H + +#include "sensorsui.h" +#include "systeminfonetworkui.h" +#include "systeminfostorageui.h" +#include "systeminfogenericui.h" + +#include <remotecontrolwidget/locationui.h> + +#include <systeminfo/qsysteminfodata_simulator_p.h> +#include <location/qgeopositioninfodata_simulator_p.h> +#include <mobilitysimulator/mobilityconnection_p.h> +#include <contacts/engines/qcontactmemorybackenddata_simulator_p.h> +#include <contacts/engines/qcontactmemorybackenddata_simulator_p.h> +#include <../plugins/sensors/simulator/qsensordata_simulator_p.h> + +class QLocalSocket; +class QLocalServer; +class MobilityData; +class MobilityClient; +namespace QtMobility { + class QContactManager; + class QContact; +} +// Required to give some slots below a connectable signature. +using namespace QtMobility; + +class MobilityServer : public QObject +{ + Q_OBJECT +public: + explicit MobilityServer(MobilityData *mobility, QObject *parent = 0); + ~MobilityServer(); + +private slots: + void newConnection(); + +private: + void removeClient(MobilityClient *c); + + QLocalServer *mServer; + QList<MobilityClient *> mClients; + + MobilityData *mMobility; + + friend class MobilityClient; +}; + +class MobilityClient : public QObject +{ + Q_OBJECT +public: + MobilityClient(qint64 pid, QLocalSocket *receiveSocket, MobilityServer *server); + ~MobilityClient(); + +public slots: + void sendSystemStorageInfo(const StorageSystemInfoUi::StorageData &data); + void sendSystemGenericInfo(const GenericSystemInfoUi::GenericData &data); + void sendSystemNetworkInfo(const NetworkSystemInfoUi::NetworkData &data); + + void sendLocationData(const LocationUi::LocationData &data); + + void sendContactData(const QContactManager &manager); + + void sendSensorsData(const SensorsUi::SensorsData &data); + +private slots: + void disconnect(); + void readyRead(); + + void sendAddedContacts(const QList<QContactLocalId> &); + void sendChangedContacts(const QList<QContactLocalId> &); + void sendRemovedContacts(const QList<QContactLocalId> &); + void sendRelationshipsFor(const QList<QContactLocalId> &); + + // called remotely + void setRequestsSystemInfo(); + void setRequestsLocationInfo(); + void setRequestsContactInfo(); + void setRequestsSensors(); + void triggerContactDataResend(); + + QtMobility::Simulator::SaveContactReply requestSaveContact(const QtMobility::QContact &contact); + int requestRemoveContact(uint id); + QtMobility::Simulator::SaveRelationshipReply requestSaveRelationship(const QtMobility::QContactRelationship &relationship); + int requestRemoveRelationship(const QtMobility::QContactRelationship &relationship); + +private: + qint64 mPid; + QLocalSocket *mReceiveSocket; + QLocalSocket *mSendSocket; + QByteArray mReadBuffer; + MobilityServer *mMobilityServer; + + bool mNotifyClientOnContactsChange; + + static int contactsClientsCount; +}; + +#endif // MOBILITY_H diff --git a/src/other/application.cpp b/src/other/application.cpp new file mode 100644 index 0000000..840709a --- /dev/null +++ b/src/other/application.cpp @@ -0,0 +1,349 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "application.h" +#include "applicationmanager.h" +#include "displaywidget.h" +#include "phononmanager.h" +#include "widgetmanager.h" +#include "widget.h" + +#include <QtCore/QTimer> +#include <QtGui/QDesktopWidget> +#include <QtGui/QApplication> +#include <QtGui/QMenu> +#include <QtNetwork/QLocalSocket> + +Application::Application(const QString &name, int id, qint64 pid, QLocalSocket *s, ApplicationManager *m) + : m_name(name) + , m_id(id) + , m_processId(pid) + , receiveSocket(s) + , sendSocket(0) + , applicationManager(m) + , mPhononManager(0) + , killTimer(0) +{ + readData(); // maybe there's already data to read + connect(receiveSocket, SIGNAL(readyRead()), this, SLOT(readData())); + connect(receiveSocket, SIGNAL(disconnected()), this, SLOT(disconnect())); + + sendSocket = new QLocalSocket(this); + sendSocket->connectToServer(QtSimulatorPrivate::qt_applicationServerName(pid)); + + QtSimulatorPrivate::qt_registerUserTypes(); +} + +Application::~Application() +{ + receiveSocket->disconnectFromServer(); + receiveSocket->deleteLater(); +} + +void Application::readData() +{ + readBuffer += receiveSocket->readAll(); + forever { + QtSimulatorPrivate::IncomingRemoteMetacall rpc; + if (rpc.read(&readBuffer)) { + bool callWasHandled = false; + callWasHandled = rpc.call(receiveSocket, this) || rpc.call(receiveSocket, mWidgetManager); + if (!callWasHandled) { + mPhononManager->setCurrentApplication(this); + callWasHandled = rpc.call(receiveSocket, mPhononManager); + } + if (callWasHandled) { + continue; + } + qWarning("Ignoring a call to %s, No such slot in the receiving objects.", rpc.signature().data()); + } + break; + } +} + +/** + * Tries hard to kill the application by regularly sending quit messages. + */ +void Application::kill() +{ + if (!killTimer) { + killTimer = new QTimer(this); + connect(killTimer, SIGNAL(timeout()), this, SLOT(kill())); + killTimer->start(100); + } + + QtSimulatorPrivate::RemoteMetacall<void>::call(sendSocket, QtSimulatorPrivate::NoSync, + "killApplication"); +} + +void Application::setPhononManager(PhononManager *manager) +{ + mPhononManager = manager; +} + +void Application::setWidgetManager(WidgetManager *wm) +{ + mWidgetManager = wm; +} + +DisplayWidget* Application::display() const +{ + return mWidgetManager->display(); +} + +int Application::createWidget(int parentId, QRect geometry, QString title) +{ + return mWidgetManager->create( + parentId, + geometry, + title, + this); +} + +QtSimulatorPrivate::DisplayInfo Application::displayInfo() +{ + return applicationManager->displayInfo(); +} + +QString Application::systemFontDirectory() +{ + return applicationManager->fontDirectory(); +} + +void Application::disconnect() +{ + this->deleteLater(); + applicationManager->unregisterApplication(m_id); +} + +void Application::updateActionFromVariantList(QAction* action, const QVariantList& list) +{ + action->setAutoRepeat(list.at(0).toBool()); + + QIcon icon = list.at(1).value<QIcon>(); + // ### don't set icons for now. Something's wrong with it. + //action->setIcon(icon); + //action->setIconText(list.at(2).toString()); + action->setCheckable(list.at(3).toBool()); + action->setChecked(list.at(4).toBool()); + action->setEnabled(list.at(5).toBool()); + action->setIconVisibleInMenu(list.at(6).toBool()); + action->setSeparator(list.at(7).toBool()); + action->setVisible(list.at(8).toBool()); + QString text = list.at(9).toString(); + action->setText(text); + action->setIconVisibleInMenu(list.at(10).toBool()); + + QtSimulatorPrivate::RemotePointer remoteMenu = list.at(11).value<QtSimulatorPrivate::RemotePointer>(); + if (remoteMenu) { + QMenu* menu = provideMenu(remoteMenu); + action->setMenu(menu); + } +} + +Application::SimulatorActionData Application::variantListToSimulatorActionData(QVariantList& list, bool createAction) +{ + SimulatorActionData item; + QVariant remotePointerVariant = list.at(12); + item.remotePointer = remotePointerVariant.value<QtSimulatorPrivate::RemotePointer>(); + + if (createAction) { + item.action = new QAction(0); + item.action->setProperty("remotePointer", remotePointerVariant); + connect(item.action, SIGNAL(triggered()), SLOT(onMenuActionTriggered())); + updateActionFromVariantList(item.action, list); + } else { + item.action = 0; + } + + return item; +} + +void Application::registerMenuBar(QtSimulatorPrivate::RemotePointer remoteMenuBar, int widgetId) +{ + //qDebug("Application::registerMenuBar"); + QMenuBar* menuBar = new QMenuBar(); + mMenuBarHash.insert(remoteMenuBar, menuBar); + menuBar->setNativeMenuBar(false); + + Widget* widget = mWidgetManager->widgetForId(widgetId); + if (widget) + widget->setMenuBar(menuBar); +} + +void Application::unregisterMenuBar(QtSimulatorPrivate::RemotePointer remoteMenuBar, int widgetId) +{ + Widget* widget = mWidgetManager->widgetForId(widgetId); + if (widget) + widget->setMenuBar(0); + + QMenuBar* menuBar = mMenuBarHash.value(remoteMenuBar, 0); + delete menuBar; + mMenuBarHash.remove(remoteMenuBar); +} + +void Application::reparentMenuBar(QtSimulatorPrivate::RemotePointer remoteMenuBar, int oldWidgetId, int newWidgetId) +{ + //qDebug("Application::reparentMenuBar from %d to %d", oldWidgetId, newWidgetId); + QMenuBar* menuBar = mMenuBarHash.value(remoteMenuBar, 0); + Widget* oldWidget = mWidgetManager->widgetForId(oldWidgetId); + Widget* newWidget = mWidgetManager->widgetForId(newWidgetId); + if (oldWidget) + oldWidget->setMenuBar(0); + if (newWidget) + newWidget->setMenuBar(menuBar); +} + +void Application::menuBarAddAction(QtSimulatorPrivate::RemotePointer remoteMenuBar, QVariantList actionData, QtSimulatorPrivate::RemotePointer remoteBeforeAction) +{ + //qDebug("Application::menuBarAddAction %p", remoteMenuBar.ptr); + QMenuBar* menuBar = mMenuBarHash.value(remoteMenuBar, 0); + if (!menuBar) { + qWarning("Application::menuBarAddAction can't find menuBar."); + return; + } + + QAction *beforeAction; + beforeAction = mActionHash.value(remoteBeforeAction, 0); + + SimulatorActionData item = variantListToSimulatorActionData(actionData); + mActionHash.insert(item.remotePointer, item.action); + + menuBar->insertAction(beforeAction, item.action); +} + +void Application::menuBarSyncAction(QVariantList actionData) +{ + //qDebug("Application::menuBarSyncAction"); + SimulatorActionData item = variantListToSimulatorActionData(actionData, false); + QAction* action = mActionHash.value(item.remotePointer, 0); + if (!action) { + qWarning("Application::menuBarSyncAction can't find action."); + return; + } + + updateActionFromVariantList(action, actionData); +} + +void Application::menuBarRemoveAction(QtSimulatorPrivate::RemotePointer remoteMenuBar, QtSimulatorPrivate::RemotePointer remoteAction) +{ + QMenuBar* menuBar = mMenuBarHash.value(remoteMenuBar, 0); + if (!menuBar) { + qWarning("Application::menuBarRemoveAction can't find menuBar."); + return; + } + QAction* action = mActionHash.value(remoteAction, 0); + if (!action) { + qWarning("Application::menuBarRemoveAction can't find action."); + return; + } + mActionHash.remove(remoteAction); + menuBar->removeAction(action); + delete action; +} + +QMenu* Application::provideMenu(QtSimulatorPrivate::RemotePointer remoteMenu) +{ + QMenu* menu = mMenuHash.value(remoteMenu, 0); + if (!menu) { + menu = new QMenu; + mMenuHash.insert(remoteMenu, menu); + } + return menu; +} + +void Application::destroyMenu(QtSimulatorPrivate::RemotePointer remoteMenu) +{ + QMenu* menu = mMenuHash.value(remoteMenu, 0); + if (!menu) { + qWarning("Application::destroyMenu can't find menu."); + return; + } + mMenuHash.remove(remoteMenu); + delete menu; +} + +void Application::menuAddAction(QtSimulatorPrivate::RemotePointer remoteMenu, QVariantList actionData, QtSimulatorPrivate::RemotePointer remoteBeforeAction) +{ + QMenu* menu = provideMenu(remoteMenu); + if (!menu) { + qWarning("Application::menuAddAction can't find menu."); + return; + } + + QAction* beforeAction = mActionHash.value(remoteBeforeAction, 0); + SimulatorActionData smi = variantListToSimulatorActionData(actionData); + menu->insertAction(beforeAction, smi.action); + mActionHash.insert(smi.remotePointer, smi.action); +} + +void Application::menuSyncAction(QVariantList actionData) +{ + SimulatorActionData smi = variantListToSimulatorActionData(actionData, false); + QAction* action = mActionHash.value(smi.remotePointer, 0); + if (!action) { + qWarning("Application::menuSyncAction can't find action."); + return; + } + updateActionFromVariantList(action, actionData); +} + +void Application::menuRemoveAction(QtSimulatorPrivate::RemotePointer remoteMenu, QtSimulatorPrivate::RemotePointer remoteAction) +{ + QMenu* menu = provideMenu(remoteMenu); + if (!menu) { + qWarning("Application::menuRemoveAction can't find menu."); + return; + } + + QAction* action = mActionHash.value(remoteAction, 0); + if (!action) { + qWarning("Application::menuRemoveAction can't find action."); + return; + } + + menu->removeAction(action); + mActionHash.remove(remoteAction); + delete action; +} + +void Application::onMenuActionTriggered() +{ + QAction* action = qobject_cast<QAction*>(sender()); + Q_ASSERT(action); + if (!action) + return; + + QVariant v = action->property("remotePointer"); + if (v.isNull()) + return; + + QtSimulatorPrivate::RemoteMetacall<void>::call(sendSocket, QtSimulatorPrivate::NoSync, + "triggerAction", v); +} diff --git a/src/other/application.h b/src/other/application.h new file mode 100644 index 0000000..fc75ff2 --- /dev/null +++ b/src/other/application.h @@ -0,0 +1,123 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef APPLICATION_H +#define APPLICATION_H + +#include "qsimulatordata_p.h" +#include <QtGui/QMenuBar> +#include <QtCore/QObject> +#include <QtCore/QRect> +#include <QtCore/QHash> + +class ApplicationManager; +class PhononManager; +class WidgetManager; +class DisplayWidget; +class QString; +class QLocalSocket; + +class Application : public QObject +{ + Q_OBJECT +public: + ~Application(); + inline QString name() const { return m_name; } + inline int id() const { return m_id; } + qint64 processId() const { return m_processId; } + + void setPhononManager(PhononManager *manager); + void setWidgetManager(WidgetManager *wm); + DisplayWidget* display() const; + QLocalSocket *socket() { return sendSocket; } + +signals: + void widgetUpdate(); + void widgetDestroyed(); + +public slots: + void readData(); + void kill(); + +private slots: + // called remotely + void disconnect(); + QtSimulatorPrivate::DisplayInfo displayInfo(); + QString systemFontDirectory(); + int createWidget(int parentId, QRect geometry, QString title); + + void registerMenuBar(QtSimulatorPrivate::RemotePointer remoteMenuBar, int widgetId); + void unregisterMenuBar(QtSimulatorPrivate::RemotePointer remoteMenuBar, int widgetId); + void reparentMenuBar(QtSimulatorPrivate::RemotePointer remoteMenuBar, int oldWidgetId, int newWidgetId); + void menuBarAddAction(QtSimulatorPrivate::RemotePointer remoteMenuBar, QVariantList actionData, QtSimulatorPrivate::RemotePointer beforeAction); + void menuBarSyncAction(QVariantList actionData); + void menuBarRemoveAction(QtSimulatorPrivate::RemotePointer remoteMenuBar, QtSimulatorPrivate::RemotePointer action); + +private: + QMenu* provideMenu(QtSimulatorPrivate::RemotePointer remoteMenu); +private slots: + void destroyMenu(QtSimulatorPrivate::RemotePointer remoteMenu); + void menuAddAction(QtSimulatorPrivate::RemotePointer menu, QVariantList actionData, QtSimulatorPrivate::RemotePointer beforeAction); + void menuSyncAction(QVariantList actionData); + void menuRemoveAction(QtSimulatorPrivate::RemotePointer menu, QtSimulatorPrivate::RemotePointer action); + void onMenuActionTriggered(); + +private: + friend class ApplicationManager; + explicit Application(const QString &name, + int id, + qint64 pid, + QLocalSocket *s, + ApplicationManager* m); + + struct SimulatorActionData + { + QAction* action; + QtSimulatorPrivate::RemotePointer remotePointer; + }; + + SimulatorActionData variantListToSimulatorActionData(QVariantList& list, bool createAction = true); + void updateActionFromVariantList(QAction* action, const QVariantList& list); + + QString m_name; + int m_id; // TODO: can we just use the process id? + qint64 m_processId; + QLocalSocket *receiveSocket, *sendSocket; + QByteArray readBuffer; + ApplicationManager *applicationManager; + PhononManager* mPhononManager; + WidgetManager *mWidgetManager; + QHash<QtSimulatorPrivate::RemotePointer, QAction*> mActionHash; + QHash<QtSimulatorPrivate::RemotePointer, QMenuBar*> mMenuBarHash; + QHash<QtSimulatorPrivate::RemotePointer, QMenu*> mMenuHash; + + QTimer *killTimer; +}; + +#endif // APPLICATION_H diff --git a/src/other/applicationmanager.cpp b/src/other/applicationmanager.cpp new file mode 100644 index 0000000..9ccfcea --- /dev/null +++ b/src/other/applicationmanager.cpp @@ -0,0 +1,382 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "application.h" +#include "applicationmanager.h" +#include "applicationtablewidget.h" +#include "deviceitem.h" +#include "widgetmanager.h" +#include "widget.h" + +#include <QtCore/QTimer> +#include <QtGui/QLayout> +#include <QtGui/QFileDialog> +#include <QtGui/QMessageBox> +#include <QtGui/QDesktopWidget> +#include <QtGui/QApplication> +#include <QtNetwork/QLocalServer> +#include <QtNetwork/QLocalSocket> + +#include <cmath> + +#ifdef Q_OS_WIN +# include <windows.h> +# include <Tlhelp32.h> +#elif defined(Q_OS_UNIX) +# include <sys/types.h> +# include <unistd.h> +# include <errno.h> +#endif + +namespace { + int gAppIdCounter = 0; +} + +ApplicationManager::ApplicationManager(QObject *parent) + : QObject(parent) + , mServer(0) + , mPhononManager(0) + , mWidgetManager(0) + , mTableWidget(0) + , mSimulatorStarted(false) +{ + // simulator socket connection + QLocalSocket checkSocket; + checkSocket.connectToServer(SIMULATOR_DISPLAY_SERVERNAME); + if (checkSocket.waitForConnected(100)) { + mSimulatorStarted = true; + return; + } + + mServer = new QLocalServer(); + QLocalServer::removeServer(SIMULATOR_DISPLAY_SERVERNAME); + if (!mServer->listen(SIMULATOR_DISPLAY_SERVERNAME)) { + qFatal("Could not open mServer"); + } + connect(mServer, SIGNAL(newConnection()), this, SLOT(handleConnection())); + connect(this, SIGNAL(applicationRegistered(Application*)), this, SLOT(registerApplication(Application*))); + + // debug window + mTableWidget = new ApplicationTableWidget(); + mConfigWidget = new QWidget(); + QHBoxLayout* layout = new QHBoxLayout; + layout->addWidget(mTableWidget); + mConfigWidget->setLayout(layout); + connect(mTableWidget, SIGNAL(killApplication(int)), this, SLOT(killApplication(int))); + + // watch for simulator clients that have been terminated + QTimer* watchDogTimer = new QTimer(this); + watchDogTimer->setObjectName(QLatin1String("watchDogTimer")); + connect(watchDogTimer, SIGNAL(timeout()), SLOT(watchDogTimer())); + watchDogTimer->start(5000); +} + +ApplicationManager::~ApplicationManager() +{ + if (mServer) { + mServer->close(); + QLocalServer::removeServer(SIMULATOR_DISPLAY_SERVERNAME); + delete mServer; + mServer = 0; + } + if (mTableWidget) + delete mTableWidget; +} + +void ApplicationManager::registerApplication(Application *newApp) +{ + mApps.push_back(newApp); + + // add to debug application table + mTableWidget->insertRow(0); + QTableWidgetItem *item = new QTableWidgetItem(QString::number(newApp->id())); + item->setData(0, newApp->id()); + mTableWidget->setItem(0, 0, item); + mTableWidget->setItem(0, 1, new QTableWidgetItem(newApp->name())); + mTableWidget->sortItems(0); + + if (mApps.size() == 1) + emit firstAppRegistered(); + //qDebug() << "ApplicationManager registered:" << newApp->name(); +} + +void ApplicationManager::unregisterApplication(int id) +{ + emit applicationUnRegistered(id); + for (int i = 0; i < mApps.size(); ++i) { + if (mApps.at(i)->id() == id) { + Application* item = mApps.takeAt(i); + //qDebug() << "ApplicationManager removes:" << item->name(); + item->deleteLater(); + + // remove from debug application table + for (int r = 0; r < mTableWidget->rowCount(); ++r) { + if (mTableWidget->item(r, 0)->data(0).toInt() == id) { + mTableWidget->removeRow(r); + break; + } + } + break; + } + } + if (mApps.isEmpty()) { + emit lastAppUnregistered(); + } +} + +bool ApplicationManager::hasApplications() const +{ + return !mApps.empty(); +} + +bool ApplicationManager::simulatorAlreadyStarted() const +{ + return mSimulatorStarted; +} + +bool ApplicationManager::initializeFontDirectory() +{ + // make sure that we have a valid font directory + QDir fontDir("fonts"); + if (!fontDir.exists()) { + QMessageBox errorMsg; + errorMsg.setWindowTitle(tr("\"%1\" folder does not exist").arg("Fonts")); + errorMsg.setText(tr("The \"%1\" folder could not be located in the installation directory.").arg("fonts")); + errorMsg.setIcon(QMessageBox::Critical); + errorMsg.exec(); + return false; + } + mFontDirectory = fontDir.absolutePath(); + return true; +} + +void ApplicationManager::killApplication(int id) +{ + for (int i = 0; i < mApps.size(); ++i) { + if (mApps.at(i)->id() == id) { + Application* item = mApps.at(i); + item->kill(); + break; + } + } +} + +void ApplicationManager::killCurrentApplication() +{ + Widget *activeWidget = mWidgetManager->activeWidget(); + if (!activeWidget) + return; + + mWidgetManager->activeWidget()->owner->kill(); +} + +void ApplicationManager::killAllApplications() +{ + foreach (Application* item, mApps) { + item->kill(); + } +} + +Application* ApplicationManager::applicationForId(int id) +{ + foreach(Application* item, mApps) { + if (item->id() == id) + return item; + } + return 0; +} + + + +void ApplicationManager::handleConnection() +{ + // get the incoming connection + QLocalSocket* socket = mServer->nextPendingConnection(); + if (!socket->isValid()) + qWarning() << "Invalid socket!"; + + using namespace QtSimulatorPrivate; + + // read the command id + qint32 requestCommand = 0; + qint64 bytesToRead = sizeof(requestCommand); + qint64 bytesRead = qt_blockingRead( + socket, reinterpret_cast<char *>(&requestCommand), bytesToRead, 500); + if (bytesRead < bytesToRead) + { + qWarning("Dropped incoming connection, couldn't read command id."); + return; + } + if (requestCommand != Command::ApplicationConnect) + { + qWarning("Dropped incoming connection, it sent an invalid command."); + return; + } + + // read the command + ApplicationConnectCommand cmd; + bytesToRead = sizeof(cmd.request); + bytesRead = qt_blockingRead( + socket, reinterpret_cast<char *>(&cmd.request), bytesToRead, 500); + if (bytesRead < bytesToRead) + { + qWarning("Dropped incoming connection, couldn't read command data."); + return; + } + + // send a reply + cmd.reply.appId = gAppIdCounter + 1; + qint64 bytesToWrite = sizeof(cmd.reply); + qint64 bytesWritten = qt_blockingWrite( + socket, reinterpret_cast<const char *>(&cmd.reply), bytesToWrite, 500); + if (bytesWritten < bytesToWrite) + { + qWarning("Dropped incoming connection, couldn't send connect reply."); + return; + } + + // success: register new application + gAppIdCounter++; + Application *app = new Application(QString::fromLatin1(cmd.request.applicationName), + cmd.reply.appId, cmd.request.applicationPid, socket, this); + app->setPhononManager(mPhononManager); + app->setWidgetManager(mWidgetManager); + emit applicationRegistered(app); +} + +void ApplicationManager::setPhononManager(PhononManager *manager) +{ + Q_ASSERT(!mPhononManager); + mPhononManager = manager; +} + +void ApplicationManager::setWidgetManager(WidgetManager *widMan) +{ + // changing the widget manager not yet supported + Q_ASSERT(!mWidgetManager); + + mWidgetManager = widMan; + + // basic display info data that's fixed for a widget manager + QImage tmp(16, 16, widMan->imageFormat()); + mDisplayInfo.format = tmp.format(); + mDisplayInfo.numColors = tmp.numColors(); + mDisplayInfo.depth = tmp.depth(); + QDesktopWidget *desktop = QApplication::desktop(); + mDisplayInfo.hostDpi = QSize(desktop->logicalDpiX(), desktop->logicalDpiY()); +} + +QString ApplicationManager::fontDirectory() +{ + return mFontDirectory; +} + +const QtSimulatorPrivate::DisplayInfo &ApplicationManager::displayInfo() +{ + return mDisplayInfo; +} + +void ApplicationManager::watchDogTimer() +{ +#ifdef Q_OS_WIN + QHash<qint64, Application*> pidMapping; + foreach (Application* app, mApps) + pidMapping.insert(app->processId(), app); + + HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapShot == INVALID_HANDLE_VALUE) { + QTimer* watchDogTimer = findChild<QTimer*>(QLatin1String("watchDogTimer")); + watchDogTimer->stop(); + qWarning("Cannot create process snapshot. Watchdog timer stopped."); + return; + } + BOOL bSuccess; + PROCESSENTRY32 processEntry; + processEntry.dwSize = sizeof(processEntry); + bSuccess = Process32First(hSnapShot, &processEntry); + while (bSuccess) { + Application* app = pidMapping.value(processEntry.th32ProcessID, 0); + if (app) + pidMapping.remove(processEntry.th32ProcessID); + bSuccess = Process32Next(hSnapShot, &processEntry); + } + CloseHandle(hSnapShot); + + QHash<qint64, Application*>::iterator it; + for (it = pidMapping.begin(); it != pidMapping.end(); ++it) + watchDogBark(it.value()); + +#elif defined(Q_OS_UNIX) + foreach (Application *app, mApps) { + pid_t pgid = getpgid(app->processId()); + if (pgid == -1 && errno == ESRCH) + watchDogBark(app); + } + +#else + QTimer* watchDogTimer = findChild<QTimer*>(QLatin1String("watchDogTimer")); + watchDogTimer->stop(); + qWarning("ApplicationManager::watchDogTimer not implemented"); +#endif +} + +void ApplicationManager::watchDogBark(Application* deadApp) +{ + qWarning() << "Application died without unregistering. Unregistering now:" << deadApp->name(); + unregisterApplication(deadApp->id()); +} + + +void ApplicationManager::updateDisplayInformation(const QSize &resolution, const DeviceData &device) +{ + using namespace std; + qreal pixelDiagonal = sqrt(pow((qreal)resolution.width(), 2) + pow((qreal)resolution.height(), 2)); + QSizeF displaySizeInch(QSizeF(resolution) * device.diagonalInInch / pixelDiagonal); + + mDisplayInfo.size = resolution; + mDisplayInfo.availableRect = device.availableGeometry; + + // calculate dpi + if (device.forceDpi != -1) { + mDisplayInfo.dpi = QSize(device.forceDpi, device.forceDpi); + } else { + mDisplayInfo.dpi.setWidth(resolution.width() / displaySizeInch.width()); + mDisplayInfo.dpi.setHeight(resolution.height() / displaySizeInch.height()); + } + + mDisplayInfo.defaultFontSize = device.defaultFontSize; + mDisplayInfo.style = device.style; + + const qreal MMperInch = 25.4; + mDisplayInfo.sizeMM = QSize(displaySizeInch.width() * MMperInch, displaySizeInch.height() * MMperInch); + + foreach (Application *application, mApps) + QtSimulatorPrivate::RemoteMetacall<void>::call(application->socket(), QtSimulatorPrivate::NoSync, + "updateDisplayInformation"); +} diff --git a/src/other/applicationmanager.h b/src/other/applicationmanager.h new file mode 100644 index 0000000..7100397 --- /dev/null +++ b/src/other/applicationmanager.h @@ -0,0 +1,100 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef APPLICATIONMANAGER_H +#define APPLICATIONMANAGER_H + +#include "qsimulatordata_p.h" +#include <QtCore/QObject> +#include <QtCore/QSize> + +class Application; +class ApplicationTableWidget; +class PhononManager; +class WidgetManager; +class QLocalServer; +class QMenuBar; +struct DeviceData; + +class ApplicationManager : public QObject +{ + Q_OBJECT +public: + ApplicationManager(QObject* parent = 0); + ~ApplicationManager(); + + Application* applicationForId(int); + void setPhononManager(PhononManager *manager); + void setWidgetManager(WidgetManager *widMan); + inline QWidget* logWidget() { return mConfigWidget; } + + QString fontDirectory(); + const QtSimulatorPrivate::DisplayInfo &displayInfo(); + + bool hasApplications() const; + bool simulatorAlreadyStarted() const; + bool initializeFontDirectory(); + +signals: + void applicationRegistered(Application*); + void applicationUnRegistered(int id); + void applicationTimedOut(int id); + void firstAppRegistered(); + void lastAppUnregistered(); + +public slots: + void handleConnection(); + void registerApplication(Application*); + void unregisterApplication(int id); + void killApplication(int id); + void killCurrentApplication(); + void killAllApplications(); + void updateDisplayInformation(const QSize &resolution, const DeviceData &device); + +protected slots: + void watchDogTimer(); + +private: + void watchDogBark(Application* deadApp); + +private: + QLocalServer *mServer; + PhononManager *mPhononManager; + WidgetManager *mWidgetManager; + QList<Application*> mApps; + ApplicationTableWidget *mTableWidget; + QWidget *mConfigWidget; + QString mFontDirectory; + + bool mSimulatorStarted; + + QtSimulatorPrivate::DisplayInfo mDisplayInfo; +}; + +#endif // APPLICATIONMANAGER_H diff --git a/src/other/configurationreader.cpp b/src/other/configurationreader.cpp new file mode 100644 index 0000000..392b2fa --- /dev/null +++ b/src/other/configurationreader.cpp @@ -0,0 +1,172 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "configurationreader.h" +#include "deviceitem.h" + +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QDebug> +#include <QtCore/QMetaEnum> + +bool ConfigurationReader::processDir(QDir *dir, QList<DeviceData>& deviceDataList) +{ + mErrorMessages.clear(); + mCurrentDir = dir; + + bool noErrors = true; + foreach (const QString& modelDirName, dir->entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { + if (!dir->cd(modelDirName)) + continue; + + foreach(const QString& fileName, dir->entryList(QStringList() << "*.config", QDir::Files)) + { + mCurrentConfigFile = dir->filePath(fileName); + QFile file(mCurrentConfigFile); + DeviceData data; + if (processFile(&file, &data)) + deviceDataList.append(data); + else + noErrors = false; + } + + dir->cdUp(); + } + + return noErrors; +} + +bool ConfigurationReader::processFile(QFile *file, DeviceData *data) +{ + if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) + return false; + + QString errorMsg; + QString fileName = file->fileName(); + int start = fileName.lastIndexOf('/'); + int end = fileName.lastIndexOf('.'); + data->name = fileName.mid(start + 1, end - start - 1); + int lineNr=0; + while (!file->atEnd()) { + lineNr++; + QByteArray line = file->readLine(); + if (!processLine(line, data, errorMsg)) { + error(tr("Error in line %1: %2").arg(lineNr).arg(errorMsg)); + errorMsg.clear(); + return false; + } + } + return true; +} + +bool ConfigurationReader::processLine(const QByteArray &line, DeviceData *deviceData, QString& errorMsg) +{ + QList<QByteArray> list = line.split(':'); + if (list.count() != 2) { + errorMsg = "ConfigurationReader: Invalid property. Syntax is name:value"; + return false; + } + QByteArray parameter = list.at(0).trimmed(); + QByteArray value = list.at(1).trimmed(); + if (parameter == "name") + deviceData->name = value; + else if (parameter == "resolutionWidth") + deviceData->resolution.setWidth(value.toInt()); + else if (parameter == "resolutionHeight") + deviceData->resolution.setHeight(value.toInt()); + else if (parameter == "diagonalInInch") + deviceData->diagonalInInch = value.toFloat(); + else if (parameter == "mockup") { + deviceData->mockupPath = mCurrentDir->filePath(value); + if (!mCurrentDir->exists(value)) { + errorMsg = tr("Mockup file %1 does not exist.").arg(deviceData->mockupPath); + return false; + } + } else if (parameter == "offsetX") + deviceData->offset.setX(value.toInt()); + else if (parameter == "offsetY") + deviceData->offset.setY(value.toInt()); + else if (parameter == "defaultFontSize") + deviceData->defaultFontSize = value.toInt(); + else if (parameter == "forceDpi") + deviceData->forceDpi = value.toInt(); + else if (parameter == "style") + deviceData->style = value; + else if (parameter == "button") { + QList<QByteArray> values = value.split(','); + if (values.count() != 6) { + errorMsg = tr("ConfigurationReader: button property requires six comma separated values\n" + " button:keycode,keytext,x,y,width,height"); + return false; + } + Button b; + const QMetaObject &qtMetaObject(QObject::staticQtMetaObject); + QMetaEnum keyEnum = qtMetaObject.enumerator(qtMetaObject.indexOfEnumerator("Key")); + int keyCode = keyEnum.keyToValue(values[0].constData()); + if (keyCode == -1) { + errorMsg = tr("ConfigurationReader: Not a valid Qt::Key name: %1").arg(values[0].data()); + return false; + } + b.key = static_cast<Qt::Key>(keyCode); + b.text = values[1]; + b.area = QRectF(values[2].toFloat(), values[3].toFloat(), + values[4].toFloat(), values[5].toFloat()); + deviceData->buttons.append(b); + } else if (parameter == "menu") { + if (value == "maemoFremantle") { + deviceData->menuType = MaemoFremantle; + } else if (value == "symbianTouch") { + deviceData->menuType = SymbianTouch; + } else { + errorMsg = tr("ConfigurationReader: menu property requires a valid type for portrait mode\n" + " (top, right, bottom, left)"); + return false; + } + } else if (parameter == "nativeOrientation") { + if (value == "landscape") + deviceData->nativeOrientation = landscapeOrientation; + else if (value == "portrait") + deviceData->nativeOrientation = portraitOrientation; + } else + return false; + return true; +} + +void ConfigurationReader::error(const QString& msg) +{ + mErrorMessages.append(mCurrentConfigFile + ": " + msg); +} + +QString ConfigurationReader::errorMessageLines() const +{ + QString msg; + foreach (const QString& str, mErrorMessages) + msg.append(str + '\n'); + return msg; +} diff --git a/src/other/configurationreader.h b/src/other/configurationreader.h new file mode 100644 index 0000000..622b2bd --- /dev/null +++ b/src/other/configurationreader.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CONFIGURATIONREADER_H +#define CONFIGURATIONREADER_H + +#include <QtCore/QObject> +#include <QtCore/QStringList> + +struct DeviceData; +class QFile; +class QDir; + +class ConfigurationReader: public QObject +{ + Q_OBJECT +public: + bool processDir(QDir *dir, QList<DeviceData>& deviceDataList); + bool processFile(QFile *file, DeviceData *data); + + QStringList errorMessages() const + { + return mErrorMessages; + } + + QString errorMessageLines() const; + +private: + bool processLine(const QByteArray &line, DeviceData* deviceData, QString& errorMsg); + void error(const QString& msg); + +private: + QDir* mCurrentDir; + QString mCurrentConfigFile; + QStringList mErrorMessages; +}; + +#endif //CONFIGURATIONREADER_H diff --git a/src/other/deviceitem.cpp b/src/other/deviceitem.cpp new file mode 100644 index 0000000..eb20339 --- /dev/null +++ b/src/other/deviceitem.cpp @@ -0,0 +1,315 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "deviceitem.h" +#include "displaywidget.h" +#include "menu.h" + +#include <qmath.h> +#include <QtCore/QState> +#include <QtCore/QSignalTransition> +#include <QtCore/QPropertyAnimation> +#include <QtGui/QGraphicsSceneMouseEvent> + +DeviceItem::DeviceItem(QGraphicsItem *parent) + : QGraphicsObject(parent) + , isLandscape(false) + , mDisplay(0) + , mMockup(0) + , mMenu(0) +{ + mMockup = new QGraphicsPixmapItem(QPixmap(), this); + mDisplay = new DisplayWidget(this); + mDisplay->setParentItem(mMockup); + + mLandscapeState = new QState; + mPortraitState = new QState; + + const int rotationDuration = 250; + mLandscapeState->assignProperty(this, "rotation", -90); + connect(mLandscapeState, SIGNAL(exited()), this, SLOT(startRotate())); + QSignalTransition *l2p = mLandscapeState->addTransition(this, "rotationSignal()", mPortraitState); + QPropertyAnimation *l2pRotAnim = new QPropertyAnimation(this, "rotation", this); + l2pRotAnim->setDuration(rotationDuration); + l2p->addAnimation(l2pRotAnim); + connect(l2pRotAnim, SIGNAL(finished()), this, SLOT(setPortrait())); + + mPortraitState->assignProperty(this, "rotation", 0); + connect(mPortraitState, SIGNAL(exited()), this, SLOT(startRotate())); + QSignalTransition *p2l = mPortraitState->addTransition(this, "rotationSignal()", mLandscapeState); + QPropertyAnimation *p2lRotAnim = new QPropertyAnimation(this, "rotation", this); + p2lRotAnim->setDuration(rotationDuration); + p2l->addAnimation(p2lRotAnim); + connect(p2lRotAnim, SIGNAL(finished()), this, SLOT(setLandscape())); + + mStateMachine.addState(mPortraitState); + mStateMachine.setInitialState(mPortraitState); + mStateMachine.addState(mLandscapeState); + mStateMachine.start(); +} + +DeviceItem::~DeviceItem() +{ + if (mMenu) { + delete mMenu; + mMenu = 0; + } +} + +DisplayWidget *DeviceItem::display() +{ + return mDisplay; +} + +QRectF DeviceItem::boundingRect() const +{ + return QRectF(QPointF(-mSize.width()/2, -mSize.height()/2), mSize); +} + +void DeviceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(painter); + Q_UNUSED(option); + Q_UNUSED(widget); +} + +void DeviceItem::changeDevice(const DeviceData &data) +{ + // the the device mockup was not yet read, do so now + if (data.mockup.isNull()) { + data.mockup = QPixmap(data.mockupPath); + if (data.mockup.isNull()) + qFatal("Could not read mockup image %s", qPrintable(data.mockupPath)); + } + + Orientation current; + if (isLandscape) + current = landscapeOrientation; + else + current = portraitOrientation; + if (data.nativeOrientation != mDeviceData.nativeOrientation) { + emit deviceChanged(current, mDeviceData.nativeOrientation, data.nativeOrientation); + } + mDeviceData = data; + + // self size + prepareGeometryChange(); + mSize = mDeviceData.mockup.size(); + + newWindowSize(); + newViewSize(); + + // mockup setup + mMockup->setPixmap(mDeviceData.mockup); + mMockup->setPos(-mSize.width()/2, -mSize.height()/2); + mMockup->setTransformOriginPoint(mSize.width()/2, mSize.height()/2); + + // button setup + qDeleteAll(mButtons); + mButtons.clear(); + foreach (const Button &buttonmDeviceData, mDeviceData.buttons) { + DeviceButton *button = new DeviceButton(buttonmDeviceData, mMockup); + connect(button, SIGNAL(pressed(Qt::Key, QString)), this, SIGNAL(buttonPressed(Qt::Key, QString))); + connect(button, SIGNAL(released(Qt::Key)), this, SIGNAL(buttonReleased(Qt::Key))); + mButtons.append(button); + } + + // menu setup + if (mMenu) { + delete mMenu; + mMenu = 0; + } + switch (mDeviceData.menuType) { + case MaemoFremantle: + mMenu = new FremantleMenu(mDisplay); + break; + case SymbianTouch: + mMenu = new SymbianTouchMenu(mDisplay); + break; + default: + break; + } + updateMenuPositionAndSize(); + mDeviceData.availableGeometry = mAvailableGeometry; + // display setup + QPoint newPos(mDeviceData.offset); + QSize newResolution(mDeviceData.resolution); + + if (isLandscape) { + newPos += QPoint(mDeviceData.resolution.width(),0); + newResolution.transpose(); + } + mDisplay->setPos(newPos); + mDisplay->setSize(newResolution); + + emit deviceChanged(newResolution, mDeviceData); +} + +void DeviceItem::toggleOrientation() +{ + emit rotationSignal(); +} + +void DeviceItem::setLandscape() +{ + isLandscape = true; + + newViewSize(); + + mDisplay->setRotation(90); + mDisplay->setX(mDeviceData.offset.x() + mDeviceData.resolution.width()); + QSize newResolution = mDeviceData.resolution; + newResolution.transpose(); + mDisplay->setSize(QSize(mDeviceData.resolution.height(), mDeviceData.resolution.width())); + + updateMenuPositionAndSize(); + mDeviceData.availableGeometry = mAvailableGeometry; + + emit deviceChanged(newResolution, mDeviceData); + emit orientationChanged(landscapeOrientation, mDeviceData.nativeOrientation); +} + +void DeviceItem::setPortrait() +{ + isLandscape = false; + + newViewSize(); + + mDisplay->setRotation(0); + mDisplay->setSize(mDeviceData.resolution); + mDisplay->setX(mDeviceData.offset.x()); + + updateMenuPositionAndSize(); + mDeviceData.availableGeometry = mAvailableGeometry; + + emit deviceChanged(mDeviceData.resolution, mDeviceData); + emit orientationChanged(portraitOrientation, mDeviceData.nativeOrientation); +} + +void DeviceItem::startRotate() +{ + // set the view to the maximum size + int rotationSide = rotationSideLength() * scale(); + setPos(rotationSide/2, rotationSide/2); + emit viewSizeRequired(QSize(rotationSide, rotationSide)); +} + +void DeviceItem::changeScaleFactor(qreal newScaleFactor) +{ + setScale(newScaleFactor); + + newWindowSize(); + newViewSize(); +} + +void DeviceItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + mDragOffset = event->scenePos().toPoint(); +} + +void DeviceItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ +#ifndef Q_WS_X11 + emit drag(event->screenPos() - mDragOffset); +#else + ungrabMouse(); + emit drag(event->screenPos()); +#endif +} + +void DeviceItem::newViewSize() +{ + QSizeF windowSize = mSize * scale(); + if (isLandscape) + windowSize.transpose(); + setPos(windowSize.width()/2, windowSize.height()/2); + emit viewSizeRequired(windowSize.toSize()); +} + +void DeviceItem::newWindowSize() +{ + int rotationSide = rotationSideLength() * scale(); + setPos(rotationSide/2, rotationSide/2); + emit sizeChanged(QSize(rotationSide, rotationSide)); +} + +int DeviceItem::rotationSideLength() +{ +#ifdef Q_OS_WIN + return sqrt(pow(mSize.width(), 2) + pow(mSize.height(), 2)); +#else + return std::max(mSize.width(), mSize.height()); +#endif +} + +void DeviceItem::updateMenuPositionAndSize() +{ + QRect displayRect; + if (isLandscape) + displayRect.setRect(0, 0, mDeviceData.resolution.height(), mDeviceData.resolution.width()); + else + displayRect.setRect(0, 0, mDeviceData.resolution.width(), mDeviceData.resolution.height()); + if (mMenu) { + mAvailableGeometry = mMenu->updateMenus(isLandscape, displayRect); + } else { + mAvailableGeometry = displayRect; + } + emit offsetChanged(mAvailableGeometry.topLeft()); +} + +DeviceButton::DeviceButton(const Button &button, QGraphicsItem *parent) + : QGraphicsObject(parent) + , mButton(button) +{ + setPos(button.area.topLeft()); +} + +QRectF DeviceButton::boundingRect() const +{ + return QRectF(QPointF(), mButton.area.size()); +} + +void DeviceButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(painter); + Q_UNUSED(option); + Q_UNUSED(widget); +} + +void DeviceButton::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + emit pressed(mButton.key, mButton.text); +} + +void DeviceButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event); + emit released(mButton.key); +} diff --git a/src/other/deviceitem.h b/src/other/deviceitem.h new file mode 100644 index 0000000..b824d14 --- /dev/null +++ b/src/other/deviceitem.h @@ -0,0 +1,173 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DEVICEITEM_H +#define DEVICEITEM_H + +#include <QtGui/QGraphicsObject> +#include <QtCore/QStateMachine> + +#define SIMULATOR_MENU_Z 10000 + +struct Button +{ + QRectF area; + QString text; + Qt::Key key; +}; + +enum MenuType { + MaemoFremantle, + SymbianTouch, + None +}; + +enum Orientation { + notSet, + portraitOrientation, + landscapeOrientation, +}; + +struct DeviceData +{ + DeviceData() + : diagonalInInch(0.) + , defaultFontSize(12) + , forceDpi(-1) + , menuType(None) + , nativeOrientation(notSet) + {} + + QString name; + QSize resolution; + QRect availableGeometry; + qreal diagonalInInch; + QString mockupPath; + mutable QPixmap mockup; + QPoint offset; + int defaultFontSize; + int forceDpi; + QList<Button> buttons; + MenuType menuType; + QString style; + Orientation nativeOrientation; +}; + +class DisplayWidget; +class Menu; +class QState; + +class DeviceButton: public QGraphicsObject +{ + Q_OBJECT +public: + explicit DeviceButton(const Button &button, QGraphicsItem *parent = 0); + + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + +protected: + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + +private: + Button mButton; + +signals: + void pressed(Qt::Key, QString) const; + void released(Qt::Key) const; +}; + +class DeviceItem: public QGraphicsObject +{ + Q_OBJECT +public: + DeviceItem(QGraphicsItem *parent = 0); + ~DeviceItem(); + + DisplayWidget *display(); + + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + +public slots: + void changeDevice(const DeviceData &data); + void toggleOrientation(); + void changeScaleFactor(qreal newScaleFactor); + +protected: + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + +private: + void newWindowSize(); + void newViewSize(); + int rotationSideLength(); + void updateMenuPositionAndSize(); + + bool isLandscape; + + DeviceData mDeviceData; + + QSizeF mSize; + QRect mAvailableGeometry; + DisplayWidget *mDisplay; + QGraphicsPixmapItem *mMockup; + + QStateMachine mStateMachine; + QState *mLandscapeState; + QState *mPortraitState; + + QPoint mDragOffset; + + QList<DeviceButton*> mButtons; + Menu *mMenu; + +private slots: + void startRotate(); + void setLandscape(); + void setPortrait(); + +signals: + void rotationSignal(); + void sizeChanged(const QSize &size); + void drag(const QPoint &to); // to is the new top-left point of the view in screen coordinates + void viewSizeRequired(const QSize &size); + + void deviceChanged(const QSize &resolution, const DeviceData &device); + void offsetChanged(const QPoint &newOffset); + + void buttonPressed(Qt::Key key, QString text); + void buttonReleased(Qt::Key key); + + void orientationChanged(Orientation current, Orientation native); + void deviceChanged(Orientation current, Orientation currentNative, Orientation targetNative); +}; + +#endif //DEVICEITEM_H diff --git a/src/other/displaywidget.cpp b/src/other/displaywidget.cpp new file mode 100644 index 0000000..7f1c638 --- /dev/null +++ b/src/other/displaywidget.cpp @@ -0,0 +1,88 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "displaywidget.h" +#include "widgetmanager.h" +#include "widget.h" + +#include <QtGui/QKeyEvent> +#include <QtGui/QPainter> + +DisplayWidget::DisplayWidget(QGraphicsItem *parent) +: QGraphicsItem(parent) +{ + setFlag(QGraphicsItem::ItemClipsChildrenToShape); +} + +int DisplayWidget::width() const +{ + return mSize.width(); +} + +int DisplayWidget::height() const +{ + return mSize.height(); +} + +QSize DisplayWidget::size() const +{ + return mSize; +} + +void DisplayWidget::setWidth(quint32 w) +{ + mSize.setWidth(w); +} + +void DisplayWidget::setHeight(quint32 h) +{ + mSize.setHeight(h); +} + +void DisplayWidget::setSize(const QSize &s) +{ + if (mSize != s) + { + mSize = s; + } +} + +QRectF DisplayWidget::boundingRect() const +{ + return QRectF(0, 0, width(), height()); +} + +void DisplayWidget::paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + painter->setBrush(QColor(0, 0, 33)); + painter->drawRect(boundingRect().toRect()); +} diff --git a/src/other/displaywidget.h b/src/other/displaywidget.h new file mode 100644 index 0000000..a8ef05b --- /dev/null +++ b/src/other/displaywidget.h @@ -0,0 +1,58 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DISPLAYWIDGET_H +#define DISPLAYWIDGET_H + +#include <QtCore/QTimer> +#include <QtGui/QGraphicsItem> + +class WidgetManager; + +class DisplayWidget : public QGraphicsItem +{ +public: + DisplayWidget(QGraphicsItem *parent = 0); + + int width() const; + int height() const; + QSize size() const; + + void setWidth(quint32 w); + void setHeight(quint32 h); + void setSize(const QSize &s); + + virtual QRectF boundingRect() const; + virtual void paint( QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + +private: + QSize mSize; +}; + +#endif // DISPLAYWIDGET_H diff --git a/src/other/menu.cpp b/src/other/menu.cpp new file mode 100644 index 0000000..8de2a53 --- /dev/null +++ b/src/other/menu.cpp @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "menu.h" +#include "menuwidget.h" + +Menu::Menu(QGraphicsItem *displayWidget, QObject *parent) +: QObject(parent) +{ + Q_UNUSED(displayWidget); +} + +Menu::~Menu(void) +{ + qDeleteAll(mMenuWidgets); + mMenuWidgets.clear(); +} + +QRect Menu::updateMenus(Orientation orientation, const QRect &displayRect) +{ + QRect mAvailableGeometry = displayRect; + bool isLandscape = true; + if (orientation == portraitOrientation) + isLandscape = false; + + foreach (MenuWidget *menu, mMenuWidgets) { + MenuWidgetType currentType = menu->currentType(isLandscape); + switch (currentType) { + case (topMenu): { + menu->setX(mAvailableGeometry.x()); + menu->setY(mAvailableGeometry.y()); + menu->setHeight(menu->currentExtend(isLandscape)); + menu->setWidth(mAvailableGeometry.width()); + mAvailableGeometry.setTop(mAvailableGeometry.top() + menu->currentExtend(isLandscape)); + break; + } case (rightMenu): { + menu->setX(mAvailableGeometry.x() + mAvailableGeometry.width() - menu->currentExtend(isLandscape)); + menu->setY(mAvailableGeometry.y()); + menu->setHeight(mAvailableGeometry.height()); + menu->setWidth(menu->currentExtend(isLandscape)); + mAvailableGeometry.setWidth(mAvailableGeometry.width() - menu->currentExtend(isLandscape)); + break; + } case (bottomMenu): { + menu->setX(mAvailableGeometry.x()); + menu->setY(mAvailableGeometry.y() + mAvailableGeometry.height() - menu->currentExtend(isLandscape)); + menu->setHeight(menu->currentExtend(isLandscape)); + menu->setWidth(mAvailableGeometry.width()); + mAvailableGeometry.setHeight(mAvailableGeometry.height() - menu->currentExtend(isLandscape)); + break; + } case (leftMenu): { + menu->setX(mAvailableGeometry.x()); + menu->setY(mAvailableGeometry.y()); + menu->setWidth(menu->currentExtend(isLandscape)); + menu->setHeight(mAvailableGeometry.height()); + mAvailableGeometry.setX(mAvailableGeometry.x() + menu->currentExtend(isLandscape)); + break; + } default: { + menu->setSize(QSize(0,0)); + break; + } + } + menu->showPixmap(isLandscape); + } + return mAvailableGeometry; +} + +QRect Menu::updateMenus(bool isLandscape, const QRect &displayRect) +{ + if (isLandscape) + return updateMenus(landscapeOrientation, displayRect); + else + return updateMenus(portraitOrientation, displayRect); +} + +FremantleMenu::FremantleMenu(QGraphicsItem *displayWidget, QObject *parent) +: Menu(displayWidget, parent) +{ + MenuWidget *menuWidget = new MenuWidget(topMenu, 57, topMenu, 56, displayWidget); + menuWidget->setPortraitPixmap(QPixmap(":/menus/fremantle_portrait.png")); + menuWidget->setLandscapePixmap(QPixmap(":/menus/fremantle_landscape.png")); + mMenuWidgets.append(menuWidget); +} + +SymbianTouchMenu::SymbianTouchMenu(QGraphicsItem *displayWidget, QObject *parent) +: Menu(displayWidget, parent) +{ + MenuWidget *menuWidget = new MenuWidget(bottomMenu, 60, rightMenu, 138, displayWidget); + menuWidget->setPortraitPixmap(QPixmap(":/menus/symbiantouch_buttons_small_portrait.png")); + menuWidget->setLandscapePixmap(QPixmap(":/menus/symbiantouch_buttons_small_landscape.png")); + mMenuWidgets.append(menuWidget); + menuWidget = new MenuWidget(topMenu, 73, topMenu, 73, displayWidget); + menuWidget->setPortraitPixmap(QPixmap(":/menus/symbiantouch_status_portrait.png")); + menuWidget->setLandscapePixmap(QPixmap(":/menus/symbiantouch_status_landscape.png")); + mMenuWidgets.append(menuWidget); +} diff --git a/src/other/menu.h b/src/other/menu.h new file mode 100644 index 0000000..7e4a459 --- /dev/null +++ b/src/other/menu.h @@ -0,0 +1,66 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MENU_H +#define MENU_H + +#include "deviceitem.h" + +#include <QtCore/QObject> + +class MenuWidget; +class QRect; +class QGraphicsItem; +class Menu : public QObject +{ + Q_OBJECT +public: + explicit Menu(QGraphicsItem *displayWidget, QObject *parent = 0); + virtual ~Menu(); + + virtual QRect updateMenus(Orientation orientation, const QRect &displayRect); + QRect updateMenus(bool isLandscape, const QRect &displayRect); + +protected: + QList<MenuWidget *> mMenuWidgets; +}; + +class FremantleMenu: public Menu +{ +public: + explicit FremantleMenu(QGraphicsItem *displayWidget, QObject *parent = 0); +}; + +class SymbianTouchMenu: public Menu +{ +public: + explicit SymbianTouchMenu(QGraphicsItem *displayWidget, QObject *parent = 0); +}; + +#endif //MENU_H diff --git a/src/other/menuwidget.cpp b/src/other/menuwidget.cpp new file mode 100644 index 0000000..150287e --- /dev/null +++ b/src/other/menuwidget.cpp @@ -0,0 +1,130 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "menuwidget.h" + +#include <QtGui/QPainter> + +MenuWidget::MenuWidget(MenuWidgetType portraitType, int portraitExtend, MenuWidgetType landscapeType, int landscapeExtend, QGraphicsItem *parent) +: QGraphicsPixmapItem(parent) +, mPortraitType(portraitType) +, mPortraitExtend(portraitExtend) +, mLandscapeType(landscapeType) +, mLandscapeExtend(landscapeExtend) +{ + setZValue(SIMULATOR_MENU_Z); +} + +MenuWidgetType MenuWidget::currentType(bool landscape) const +{ + if (landscape) + return mLandscapeType; + else + return mPortraitType; +} + +int MenuWidget::currentExtend(bool landscape) const +{ + if (landscape) + return mLandscapeExtend; + else + return mPortraitExtend; +} + +MenuWidgetType MenuWidget::landscapeType() const +{ + return mLandscapeType; +} + +MenuWidgetType MenuWidget::portraitType() const +{ + return mPortraitType; +} + +int MenuWidget::portraitExtend() const +{ + return mPortraitExtend; +} + +int MenuWidget::landscapeExtend() const +{ + return mLandscapeExtend; +} + +int MenuWidget::width() const +{ + return mSize.width(); +} + +int MenuWidget::height() const +{ + return mSize.height(); +} + +QSize MenuWidget::size() const +{ + return mSize; +} + +void MenuWidget::setWidth(quint32 w) +{ + mSize.setWidth(w); +} + +void MenuWidget::setHeight(quint32 h) +{ + mSize.setHeight(h); +} + +void MenuWidget::setSize(const QSize &s) +{ + if (mSize != s) + { + mSize = s; + } +} + +void MenuWidget::showPixmap(bool isLandscape) +{ + if (isLandscape) + setPixmap(mLandscapePixmap); + else + setPixmap(mPortraitPixmap); + show(); +} + +void MenuWidget::setPortraitPixmap(const QPixmap &portraitPixmap) +{ + mPortraitPixmap = portraitPixmap; +} + +void MenuWidget::setLandscapePixmap(const QPixmap &landscapePixmap) +{ + mLandscapePixmap = landscapePixmap; +} diff --git a/src/other/menuwidget.h b/src/other/menuwidget.h new file mode 100644 index 0000000..d66a7e1 --- /dev/null +++ b/src/other/menuwidget.h @@ -0,0 +1,80 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MENUWIDGET_H +#define MENUWIDGET_H + +#include "deviceitem.h" + +#include <QtGui/QGraphicsObject> + +enum MenuWidgetType { + topMenu, + leftMenu, + bottomMenu, + rightMenu, + noMenu +}; + +class MenuWidget : public QGraphicsPixmapItem +{ +public: + enum {MenuType = UserType + 2}; + MenuWidget(MenuWidgetType type, int portraitExtend, MenuWidgetType landscapeType, int landscapeExtend, QGraphicsItem *parent = 0); + + MenuWidgetType currentType(bool landscape) const; + int currentExtend(bool landscape) const; + MenuWidgetType portraitType() const; + int portraitExtend() const; + MenuWidgetType landscapeType() const; + int landscapeExtend() const; + + int type() const {return MenuType;}; + int width() const; + int height() const; + QSize size() const; + + void showPixmap(bool isLandscape); + void setPortraitPixmap(const QPixmap &portraitPixmap); + void setLandscapePixmap(const QPixmap &landscapePixmap); + void setWidth(quint32 w); + void setHeight(quint32 h); + void setSize(const QSize &s); + +private: + QSize mSize; + MenuWidgetType mPortraitType; + int mPortraitExtend; + QPixmap mPortraitPixmap; + MenuWidgetType mLandscapeType; + int mLandscapeExtend; + QPixmap mLandscapePixmap; +}; + +#endif // MENUWIDGET_H diff --git a/src/other/other.pri b/src/other/other.pri new file mode 100644 index 0000000..56f4ee1 --- /dev/null +++ b/src/other/other.pri @@ -0,0 +1,36 @@ +INCLUDEPATH += src/other \ + $$QT_NOKIA_SDK_PATH/src/gui/kernel \ + $$QT_NOKIA_SDK_PATH/src/plugins/phonon/simulator/shared +DEPENDPATH += src/other +SOURCES += application.cpp \ + applicationmanager.cpp \ + configurationreader.cpp \ + deviceitem.cpp \ + displaywidget.cpp \ + menu.cpp \ + menuwidget.cpp \ + phononmanager.cpp \ + widgetmanager.cpp \ + widget.cpp +HEADERS += application.h \ + applicationmanager.h \ + configurationreader.h \ + deviceitem.h \ + displaywidget.h \ + menu.h \ + menuwidget.h \ + phononmanager.h \ + widgetmanager.h \ + widget.h + +contains(QT_CONFIG, phonon) { + SOURCES += \ + phononsignalbridges.cpp \ + phononvideowidget.cpp + HEADERS += \ + phononsignalbridges.h \ + phononvideowidget.h +} + +HEADERS += $$QT_NOKIA_SDK_PATH/src/plugins/phonon/simulator/shared/phononsimulatorhelpers.h +SOURCES += $$QT_NOKIA_SDK_PATH/src/plugins/phonon/simulator/shared/phononsimulatorhelpers.cpp diff --git a/src/other/phononmanager.cpp b/src/other/phononmanager.cpp new file mode 100644 index 0000000..110b18e --- /dev/null +++ b/src/other/phononmanager.cpp @@ -0,0 +1,737 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "phononmanager.h" +#include "application.h" +#include "displaywidget.h" +#include "widgetmanager.h" +#include "widget.h" + +#include <QtCore/QTimer> +#include <QtCore/QDebug> +#include <qsimulatordata_p.h> + +PhononManager::PhononManager(QObject *parent) +: QObject(parent), + mBackend(0), + mCurrentApplication(0) +{ + Phonon::Simulator::qt_registerPhononSimulatorTypes(); +} + +PhononManager::~PhononManager() +{ +} + +QSet<QObject*> PhononManager::createObjectSet(const QVariantList& vlist) +{ + QSet<QObject*> objectSet; + bool ok; + foreach (const QVariant &v, vlist) { + int i = v.toInt(&ok); + if (!ok) + continue; + objectSet.insert(reinterpret_cast<QObject*>(i)); + } + return objectSet; +} + +#ifndef QT_NO_PHONON +#include "phononsignalbridges.h" +#include "phononvideowidget.h" +#include <phonon/audiooutput.h> +#include <phonon/audiooutputinterface.h> +#include <phonon/effect.h> +#include <phonon/backendinterface.h> +#include <phonon/medianode.h> +#include <phonon/mediaobject.h> +#include <phonon/videowidget.h> +#include <phonon/private/factory_p.h> + +void PhononManager::backend_init() +{ + QObject* phononBackend = Phonon::Factory::backend(); + mBackend = qobject_cast<Phonon::BackendInterface*>(phononBackend); + BackendSignalBridge* bridge = new BackendSignalBridge(mCurrentApplication, phononBackend); + bridge->setObjectName("backend signal bridge"); +} + +inline Phonon::MediaNode* castIdToMediaNode(const Phonon::Simulator::Pointer& p) +{ + QObject* qobj = reinterpret_cast<QObject*>(p.ptr); + MediaNode* node = qobject_cast<MediaObject*>(qobj); + if (!node) + node = qobject_cast<AudioOutput*>(qobj); + if (!node) + node = qobject_cast<Effect*>(qobj); + if (!node) + node = qobject_cast<VideoWidget*>(qobj); + return node; +} + +void PhononManager::backend_destroyObjects(QVariantList vl) +{ + //qDebug("PhononManager::backend_destroyObjects"); + foreach (const QVariant &v, vl) { + Simulator::Pointer p = v.value<Simulator::Pointer>(); + MediaNode* mediaNode = castIdToMediaNode(p); + delete mediaNode; + } +} + +QStringList PhononManager::backend_availableMimeTypes() +{ + return mBackend->availableMimeTypes(); +} + +QStringList PhononManager::backend_objectDescriptionIndexes(int type) +{ + QStringList ret; + foreach (int idx, mBackend->objectDescriptionIndexes(static_cast<Phonon::ObjectDescriptionType>(type))) + ret.append(QString::number(idx)); + return ret; +} + +QHash<QString, QVariant> PhononManager::backend_objectDescriptionProperties(int type, int index) +{ + QHash<QByteArray, QVariant> props; + props = mBackend->objectDescriptionProperties(static_cast<Phonon::ObjectDescriptionType>(type), index); + + QHash<QByteArray, QVariant>::const_iterator it = props.constBegin(); + QHash<QByteArray, QVariant>::const_iterator itEnd = props.constEnd(); + + QHash<QString, QVariant> ret; + for (; it != itEnd; ++it) + ret.insert(QString::fromLocal8Bit(it.key()), it.value()); + + return ret; +} + +Phonon::Simulator::Pointer PhononManager::backend_createObject(int c, const QVariantList args) +{ + Phonon::BackendInterface::Class classId = static_cast<Phonon::BackendInterface::Class>(c); + + QObject* phononObj = 0; + PhononSignalBridge* bridge = 0; + Phonon::Simulator::Pointer ret; + switch (classId) + { + case Phonon::BackendInterface::MediaObjectClass: + phononObj = new MediaObject(mCurrentApplication); + bridge = new PhononMediaObjectSignalBridge(mCurrentApplication, phononObj); + break; + case Phonon::BackendInterface::AudioOutputClass: + phononObj = new AudioOutput(mCurrentApplication); + bridge = new PhononAudioOutputSignalBridge(mCurrentApplication, phononObj); + break; + case Phonon::BackendInterface::EffectClass: + if (args.isEmpty()) { + qWarning("PhononManager::backend_createObject can't create Phonon::Effect. Parameter missing."); + return ret; + } + qWarning("PhononManager::backend_createObject ### Effect creation not implemented."); + //phononObj = new Effect(m_audioEffects[ args[0].toInt() ], mCurrentApplication); + break; + case Phonon::BackendInterface::VideoWidgetClass: + { + PhononVideoWidget* simulatorVideoWidget = new PhononVideoWidget(mCurrentApplication); + phononObj = simulatorVideoWidget->videoWidget(); + break; + } + default: + return ret; + } + + //qDebug() << "PhononManager::backend_createObject" << c << args << phononObj; + ret.ptr = phononObj; + return ret; +} + +bool PhononManager::backend_startConnectionChange(QVariantList objects) +{ + return mBackend->startConnectionChange(createObjectSet(objects)); +} + +bool PhononManager::backend_endConnectionChange(QVariantList objects) +{ + return mBackend->endConnectionChange(createObjectSet(objects)); +} + +bool PhononManager::backend_connectNodes(Phonon::Simulator::Pointer _source, Phonon::Simulator::Pointer _sink) +{ + //qDebug("PhononManager::backend_connectNodes(%d, %d)", _source, _sink); + MediaNode* sourceNode = castIdToMediaNode(_source); + MediaNode* sinkNode = castIdToMediaNode(_sink); + Q_ASSERT(sourceNode); + Q_ASSERT(sinkNode); + Path path = createPath(sourceNode, sinkNode); + return path.isValid(); +} + +bool PhononManager::backend_disconnectNodes(Phonon::Simulator::Pointer _source, Phonon::Simulator::Pointer _sink) +{ + //qDebug("PhononManager::backend_disconnectNodes(%d, %d)", _source, _sink); + MediaNode* sourceNode = castIdToMediaNode(_source); + MediaNode* sinkNode = castIdToMediaNode(_sink); + Q_ASSERT(sourceNode); + Q_ASSERT(sinkNode); + + bool ret = false; + foreach (Path p, sourceNode->outputPaths()) { + if (p.sink() == sinkNode) { + ret = p.disconnect(); + break; + } + } + + return ret; +} + +inline Phonon::MediaObject* castIdToMediaObject(const Phonon::Simulator::Pointer& p) +{ + return qobject_cast<Phonon::MediaObject*>(reinterpret_cast<QObject*>(p.ptr)); +} + +int PhononManager::mediaObject_state(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->state() : Phonon::ErrorState; +} + +bool PhononManager::mediaObject_hasVideo(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->hasVideo() : false; +} + +bool PhononManager::mediaObject_isSeekable(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->isSeekable() : false; +} + +qint64 PhononManager::mediaObject_totalTime(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->totalTime() : 0; +} + +qint64 PhononManager::mediaObject_currentTime(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->currentTime() : 0; +} + +int PhononManager::mediaObject_tickInterval(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->tickInterval() : 0; +} + +void PhononManager::mediaObject_setTickInterval(Phonon::Simulator::Pointer id, int newTickInterval) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->setTickInterval(newTickInterval); +} + +void PhononManager::mediaObject_pause(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->pause(); +} + +void PhononManager::mediaObject_stop(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->stop(); +} + +void PhononManager::mediaObject_play(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->play(); +} + +QString PhononManager::mediaObject_errorString(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->errorString() : QString(); +} + +int PhononManager::mediaObject_errorType(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->errorType() : Phonon::FatalError; +} + +int PhononManager::mediaObject_prefinishMark(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->prefinishMark() : 0; +} + +void PhononManager::mediaObject_setPrefinishMark(Phonon::Simulator::Pointer id, int newPrefinishMark) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->setPrefinishMark(newPrefinishMark); +} + +int PhononManager::mediaObject_transitionTime(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->transitionTime() : 0; +} + +void PhononManager::mediaObject_setTransitionTime(Phonon::Simulator::Pointer id, int t) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->setTransitionTime(t); +} + +qint64 PhononManager::mediaObject_remainingTime(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + return mo ? mo->remainingTime() : 0; +} + +QVariantList PhononManager::mediaObject_source(Phonon::Simulator::Pointer id) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (!mo) + return QVariantList(); + + return Phonon::Simulator::mediaSourceToVariantList(mo->currentSource()); +} + +void PhononManager::mediaObject_setSource(Phonon::Simulator::Pointer id, const QVariantList& vl) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) + mo->setCurrentSource(Phonon::Simulator::mediaSourceFromVariantList(vl)); +} + +void PhononManager::mediaObject_setNextSource(Phonon::Simulator::Pointer id, const QVariantList& vl) +{ + Q_UNUSED(id); + Q_UNUSED(vl); + // ### not sure if we must handle this... + Q_UNUSED(id); + Q_UNUSED(vl); + + //Phonon::MediaObject* mo = castIdToMediaObject(id); + //if (mo) + // mo->setNextSource(Phonon::Simulator::mediaSourceFromVariantList(vl)); +} + +void PhononManager::mediaObject_seek(Phonon::Simulator::Pointer id, qlonglong t) +{ + Phonon::MediaObject* mo = castIdToMediaObject(id); + if (mo) mo->seek(t); +} + +inline Phonon::AudioOutput* castIdToAudioOutput(const Phonon::Simulator::Pointer& p) +{ + return qobject_cast<Phonon::AudioOutput*>(reinterpret_cast<QObject*>(p.ptr)); +} + +int PhononManager::audioOutput_outputDevice(Phonon::Simulator::Pointer id) +{ + Phonon::AudioOutput* iface = castIdToAudioOutput(id); + return iface ? iface->outputDevice().index() : -1; +} + +void PhononManager::audioOutput_setVolume(Phonon::Simulator::Pointer id, double v) +{ + Phonon::AudioOutput* iface = castIdToAudioOutput(id); + if (iface) iface->setVolume(v); +} + +bool PhononManager::audioOutput_setOutputDevice(Phonon::Simulator::Pointer id, int newDevice) +{ + Phonon::AudioOutput* iface = castIdToAudioOutput(id); + return iface ? iface->setOutputDevice(AudioOutputDevice::fromIndex(newDevice)) : -1; +} + +double PhononManager::audioOutput_volume(Phonon::Simulator::Pointer id) +{ + Phonon::AudioOutput* iface = castIdToAudioOutput(id); + return iface ? iface->volume() : 0; +} + +inline Phonon::VideoWidget* castIdToVideoWidget(const Phonon::Simulator::Pointer& p) +{ + return qobject_cast<Phonon::VideoWidget*>(reinterpret_cast<QObject*>(p.ptr)); +} + +void PhononManager::videoWidget_setAspectRatio(Phonon::Simulator::Pointer id, int r) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->setAspectRatio(static_cast<Phonon::VideoWidget::AspectRatio>(r)); +} + +void PhononManager::videoWidget_setScaleMode(Phonon::Simulator::Pointer id, int m) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->setScaleMode(static_cast<Phonon::VideoWidget::ScaleMode>(m)); +} + +void PhononManager::videoWidget_setBrightness(Phonon::Simulator::Pointer id, qreal b) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->setBrightness(b); +} + +void PhononManager::videoWidget_setContrast(Phonon::Simulator::Pointer id, qreal c) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->setContrast(c); +} + +void PhononManager::videoWidget_setHue(Phonon::Simulator::Pointer id, qreal h) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->setHue(h); +} + +void PhononManager::videoWidget_setSaturation(Phonon::Simulator::Pointer id, qreal s) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->setSaturation(s); +} + +int PhononManager::videoWidget_aspectRatio(Phonon::Simulator::Pointer id) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + return vw ? static_cast<int>(vw->aspectRatio()) : 0; +} + +int PhononManager::videoWidget_scaleMode(Phonon::Simulator::Pointer id) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + return vw ? static_cast<int>(vw->scaleMode()) : 0; +} + +qreal PhononManager::videoWidget_brightness(Phonon::Simulator::Pointer id) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + return vw ? vw->brightness() : 0; +} + +qreal PhononManager::videoWidget_contrast(Phonon::Simulator::Pointer id) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + return vw ? vw->contrast() : 0; +} + +qreal PhononManager::videoWidget_hue(Phonon::Simulator::Pointer id) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + return vw ? vw->hue() : 0; +} + +qreal PhononManager::videoWidget_saturation(Phonon::Simulator::Pointer id) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + return vw ? vw->saturation() : 0; +} + +void PhononManager::videoWidget_moveEvent(Phonon::Simulator::Pointer id, QPoint pos) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->move(pos); +} + +void PhononManager::videoWidget_resizeEvent(Phonon::Simulator::Pointer id, QSize s) +{ + Phonon::VideoWidget* vw = castIdToVideoWidget(id); + if (vw) + vw->resize(s); +} + +#else // QT_NO_PHONON + +void PhononManager::backend_init() +{ + qWarning() << "Client tries to use phonon, but the simulator isn't built with phonon support."; +} + +void PhononManager::backend_destroyObjects(QVariantList vl) +{ + Q_UNUSED(vl); +} + +QStringList PhononManager::backend_availableMimeTypes() +{ + return QStringList(); +} + +QStringList PhononManager::backend_objectDescriptionIndexes(int) +{ + return QStringList(); +} + +QHash<QString, QVariant> PhononManager::backend_objectDescriptionProperties(int, int) +{ + return QHash<QString, QVariant>(); +} + +Phonon::Simulator::Pointer PhononManager::backend_createObject(int, const QVariantList) +{ + Phonon::Simulator::Pointer pointer; + pointer.ptr = 0; + return pointer; +} + +bool PhononManager::backend_startConnectionChange(QVariantList) +{ + return false; +} + +bool PhononManager::backend_endConnectionChange(QVariantList) +{ + return false; +} + +bool PhononManager::backend_connectNodes(Phonon::Simulator::Pointer, Phonon::Simulator::Pointer) +{ + return false; +} + +bool PhononManager::backend_disconnectNodes(Phonon::Simulator::Pointer, Phonon::Simulator::Pointer) +{ + return false; +} + +int PhononManager::mediaObject_state(Phonon::Simulator::Pointer) +{ + return 0; +} + +bool PhononManager::mediaObject_hasVideo(Phonon::Simulator::Pointer) +{ + return false; +} + +bool PhononManager::mediaObject_isSeekable(Phonon::Simulator::Pointer) +{ + return false; +} + +qint64 PhononManager::mediaObject_totalTime(Phonon::Simulator::Pointer) +{ + return 0; +} + +qint64 PhononManager::mediaObject_currentTime(Phonon::Simulator::Pointer) +{ + return 0; +} + +int PhononManager::mediaObject_tickInterval(Phonon::Simulator::Pointer) +{ + return 0; +} + +void PhononManager::mediaObject_setTickInterval(Phonon::Simulator::Pointer, int) +{ +} + +void PhononManager::mediaObject_pause(Phonon::Simulator::Pointer) +{ +} + +void PhononManager::mediaObject_stop(Phonon::Simulator::Pointer) +{ +} + +void PhononManager::mediaObject_play(Phonon::Simulator::Pointer) +{ +} + +QString PhononManager::mediaObject_errorString(Phonon::Simulator::Pointer) +{ + return QString("Simulator does not support phonon"); +} + +int PhononManager::mediaObject_errorType(Phonon::Simulator::Pointer) +{ + return 0; +} + +int PhononManager::mediaObject_prefinishMark(Phonon::Simulator::Pointer) +{ + return 0; +} + +void PhononManager::mediaObject_setPrefinishMark(Phonon::Simulator::Pointer, int) +{ +} + +int PhononManager::mediaObject_transitionTime(Phonon::Simulator::Pointer) +{ + return 0; +} + +void PhononManager::mediaObject_setTransitionTime(Phonon::Simulator::Pointer, int) +{ +} + +qint64 PhononManager::mediaObject_remainingTime(Phonon::Simulator::Pointer) +{ + return 0; +} + +QVariantList PhononManager::mediaObject_source(Phonon::Simulator::Pointer) +{ + return QVariantList(); +} + +void PhononManager::mediaObject_setSource(Phonon::Simulator::Pointer, const QVariantList&) +{ +} + +void PhononManager::mediaObject_setNextSource(Phonon::Simulator::Pointer, const QVariantList&) +{ +} + +void PhononManager::mediaObject_seek(Phonon::Simulator::Pointer, qlonglong) +{ +} + +int PhononManager::audioOutput_outputDevice(Phonon::Simulator::Pointer) +{ + return 0; +} + +void PhononManager::audioOutput_setVolume(Phonon::Simulator::Pointer, double) +{ +} + +bool PhononManager::audioOutput_setOutputDevice(Phonon::Simulator::Pointer, int) +{ + return false; +} + +double PhononManager::audioOutput_volume(Phonon::Simulator::Pointer) +{ + return 0; +} + +void PhononManager::videoWidget_setAspectRatio(Phonon::Simulator::Pointer id, int r) +{ + Q_UNUSED(id); + Q_UNUSED(r); +} + +void PhononManager::videoWidget_setScaleMode(Phonon::Simulator::Pointer id, int m) +{ + Q_UNUSED(id); + Q_UNUSED(m); +} + +void PhononManager::videoWidget_setBrightness(Phonon::Simulator::Pointer id, qreal b) +{ + Q_UNUSED(id); + Q_UNUSED(b); +} + +void PhononManager::videoWidget_setContrast(Phonon::Simulator::Pointer id, qreal c) +{ + Q_UNUSED(id); + Q_UNUSED(c); +} + +void PhononManager::videoWidget_setHue(Phonon::Simulator::Pointer id, qreal h) +{ + Q_UNUSED(id); + Q_UNUSED(h); +} + +void PhononManager::videoWidget_setSaturation(Phonon::Simulator::Pointer id, qreal s) +{ + Q_UNUSED(id); + Q_UNUSED(s); +} + +int PhononManager::videoWidget_aspectRatio(Phonon::Simulator::Pointer id) +{ + Q_UNUSED(id); + return 0; +} + +int PhononManager::videoWidget_scaleMode(Phonon::Simulator::Pointer id) +{ + Q_UNUSED(id); + return 0; +} + +qreal PhononManager::videoWidget_brightness(Phonon::Simulator::Pointer id) +{ + Q_UNUSED(id); + return 0.0f; +} + +qreal PhononManager::videoWidget_contrast(Phonon::Simulator::Pointer id) +{ + Q_UNUSED(id); + return 0.0f; +} + +qreal PhononManager::videoWidget_hue(Phonon::Simulator::Pointer id) +{ + Q_UNUSED(id); + return 0.0f; +} + +qreal PhononManager::videoWidget_saturation(Phonon::Simulator::Pointer id) +{ + Q_UNUSED(id); + return 0.0f; +} + +void PhononManager::videoWidget_moveEvent(Phonon::Simulator::Pointer id, QPoint pos) +{ + Q_UNUSED(id); + Q_UNUSED(pos); +} + +void PhononManager::videoWidget_resizeEvent(Phonon::Simulator::Pointer id, QSize s) +{ + Q_UNUSED(id); + Q_UNUSED(s); +} + +#endif // else QT_NO_PHONON diff --git a/src/other/phononmanager.h b/src/other/phononmanager.h new file mode 100644 index 0000000..ee5197d --- /dev/null +++ b/src/other/phononmanager.h @@ -0,0 +1,120 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef __PHONONMANAGER_H__ +#define __PHONONMANAGER_H__ + +#include <phononsimulatorhelpers.h> + +#include <QtCore/QObject> +#include <QtCore/QVariant> +#include <QtCore/QHash> +#include <QtCore/QStringList> +#include <QtCore/QSize> +#include <QtCore/QPoint> + +class Application; + +namespace Phonon { + class BackendInterface; +} + +class PhononManager : public QObject +{ + Q_OBJECT +public: + PhononManager(QObject *parent = 0); + ~PhononManager(); + + void setCurrentApplication(Application* app) { mCurrentApplication = app; } + +private slots: + void backend_init(); + void backend_destroyObjects(QVariantList); + QStringList backend_availableMimeTypes(); + QStringList backend_objectDescriptionIndexes(int type); + QHash<QString, QVariant> backend_objectDescriptionProperties(int type, int index); + Phonon::Simulator::Pointer backend_createObject(int c, const QVariantList args); + bool backend_startConnectionChange(QVariantList objects); + bool backend_endConnectionChange(QVariantList objects); + bool backend_connectNodes(Phonon::Simulator::Pointer _source, Phonon::Simulator::Pointer _sink); + bool backend_disconnectNodes(Phonon::Simulator::Pointer _source, Phonon::Simulator::Pointer _sink); + + int mediaObject_state(Phonon::Simulator::Pointer id); + bool mediaObject_hasVideo(Phonon::Simulator::Pointer id); + bool mediaObject_isSeekable(Phonon::Simulator::Pointer id); + qint64 mediaObject_totalTime(Phonon::Simulator::Pointer id); + qint64 mediaObject_currentTime(Phonon::Simulator::Pointer id); + int mediaObject_tickInterval(Phonon::Simulator::Pointer id); + void mediaObject_setTickInterval(Phonon::Simulator::Pointer id, int newTickInterval); + void mediaObject_pause(Phonon::Simulator::Pointer id); + void mediaObject_stop(Phonon::Simulator::Pointer id); + void mediaObject_play(Phonon::Simulator::Pointer id); + QString mediaObject_errorString(Phonon::Simulator::Pointer id); + int mediaObject_errorType(Phonon::Simulator::Pointer id); + int mediaObject_prefinishMark(Phonon::Simulator::Pointer id); + void mediaObject_setPrefinishMark(Phonon::Simulator::Pointer id, int newPrefinishMark); + int mediaObject_transitionTime(Phonon::Simulator::Pointer id); + void mediaObject_setTransitionTime(Phonon::Simulator::Pointer id, int t); + qint64 mediaObject_remainingTime(Phonon::Simulator::Pointer id); + QVariantList mediaObject_source(Phonon::Simulator::Pointer id); + void mediaObject_setSource(Phonon::Simulator::Pointer id, const QVariantList&); + void mediaObject_setNextSource(Phonon::Simulator::Pointer id, const QVariantList&); + void mediaObject_seek(Phonon::Simulator::Pointer id, qlonglong t); + + int audioOutput_outputDevice(Phonon::Simulator::Pointer id); + void audioOutput_setVolume(Phonon::Simulator::Pointer id, double v); + bool audioOutput_setOutputDevice(Phonon::Simulator::Pointer id, int newDevice); + double audioOutput_volume(Phonon::Simulator::Pointer id); + + void videoWidget_setAspectRatio(Phonon::Simulator::Pointer id, int r); + void videoWidget_setScaleMode(Phonon::Simulator::Pointer id, int m); + void videoWidget_setBrightness(Phonon::Simulator::Pointer id, qreal b); + void videoWidget_setContrast(Phonon::Simulator::Pointer id, qreal c); + void videoWidget_setHue(Phonon::Simulator::Pointer id, qreal h); + void videoWidget_setSaturation(Phonon::Simulator::Pointer id, qreal s); + int videoWidget_aspectRatio(Phonon::Simulator::Pointer id); + int videoWidget_scaleMode(Phonon::Simulator::Pointer id); + qreal videoWidget_brightness(Phonon::Simulator::Pointer id); + qreal videoWidget_contrast(Phonon::Simulator::Pointer id); + qreal videoWidget_hue(Phonon::Simulator::Pointer id); + qreal videoWidget_saturation(Phonon::Simulator::Pointer id); + + void videoWidget_moveEvent(Phonon::Simulator::Pointer id, QPoint pos); + void videoWidget_resizeEvent(Phonon::Simulator::Pointer id, QSize s); + +private: + QSet<QObject*> createObjectSet(const QVariantList& vlist); + +private: + Phonon::BackendInterface* mBackend; + Application* mCurrentApplication; +}; + +#endif // __PHONONMANAGER_H__ diff --git a/src/other/phononsignalbridges.cpp b/src/other/phononsignalbridges.cpp new file mode 100644 index 0000000..10bb731 --- /dev/null +++ b/src/other/phononsignalbridges.cpp @@ -0,0 +1,167 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "phononsignalbridges.h" +#include "application.h" + +#include <qsimulatordata_p.h> +#include <phononsimulatorhelpers.h> +#include <QtCore/QStringList> + +BackendSignalBridge::BackendSignalBridge(Application* app, QObject* sender) +: PhononSignalBridge(app, sender) +{ + connect(sender, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), SLOT(on_backend_ObjectDescriptionChanged(ObjectDescriptionType))); +} + +void BackendSignalBridge::on_backend_ObjectDescriptionChanged(ObjectDescriptionType odt) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "backend_objectDescriptionChanged", remoteId(), static_cast<int>(odt)); +} + +PhononMediaObjectSignalBridge::PhononMediaObjectSignalBridge(Application* app, QObject* sender) +: PhononSignalBridge(app, sender) +{ + connect(sender, SIGNAL(aboutToFinish()), SLOT(aboutToFinish())); + connect(sender, SIGNAL(bufferStatus(int)), SLOT(bufferStatus(int))); + connect(sender, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)), SLOT(currentSourceChanged(const Phonon::MediaSource&))); + connect(sender, SIGNAL(finished()), SLOT(finished())); + connect(sender, SIGNAL(hasVideoChanged(bool)), SLOT(hasVideoChanged(bool))); + connect(sender, SIGNAL(metaDataChanged()), SLOT(metaDataChanged())); + connect(sender, SIGNAL(prefinishMarkReached(qint32)), SLOT(prefinishMarkReached(qint32))); + connect(sender, SIGNAL(seekableChanged(bool)), SLOT(seekableChanged(bool))); + connect(sender, SIGNAL(stateChanged(Phonon::State, Phonon::State)), SLOT(stateChanged(Phonon::State, Phonon::State))); + connect(sender, SIGNAL(tick(qint64)), SLOT(tick(qint64))); + connect(sender, SIGNAL(totalTimeChanged(qint64)), SLOT(totalTimeChanged(qint64))); +} + +void PhononMediaObjectSignalBridge::aboutToFinish() +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_aboutToFinish", remoteId()); +} + +void PhononMediaObjectSignalBridge::bufferStatus(int percentFilled) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_bufferStatus", remoteId(), percentFilled); +} + +void PhononMediaObjectSignalBridge::currentSourceChanged(const MediaSource& newSource) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_currentSourceChanged", remoteId(), Phonon::Simulator::mediaSourceToVariantList(newSource)); +} + +void PhononMediaObjectSignalBridge::finished() +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_finished", remoteId()); +} + +void PhononMediaObjectSignalBridge::hasVideoChanged(bool hasVideo) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_hasVideoChanged", remoteId(), hasVideo); +} + +void PhononMediaObjectSignalBridge::metaDataChanged() +{ + QStringList payload; + QMultiMap<QString, QString> metaData = mediaObject()->metaData(); + QMultiMap<QString, QString>::const_iterator it = metaData.begin(); + for (; it != metaData.end(); ++it) + payload << it.key() << it.value(); + + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_metaDataChanged", remoteId(), payload); +} + +void PhononMediaObjectSignalBridge::prefinishMarkReached(qint32 msecToEnd) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_prefinishMarkReached", remoteId(), msecToEnd); +} + +void PhononMediaObjectSignalBridge::seekableChanged(bool isSeekable) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_seekableChanged", remoteId(), isSeekable); +} + +void PhononMediaObjectSignalBridge::stateChanged(Phonon::State newstate, Phonon::State oldstate) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_stateChanged", remoteId(), (int)newstate, (int)oldstate); +} + +void PhononMediaObjectSignalBridge::tick(qint64 time) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_tick", remoteId(), time); +} + +void PhononMediaObjectSignalBridge::totalTimeChanged(qint64 newTotalTime) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "mediaObject_totalTimeChanged", remoteId(), newTotalTime); +} + +PhononAudioOutputSignalBridge::PhononAudioOutputSignalBridge(Application* app, QObject* sender) +: PhononSignalBridge(app, sender) +{ + connect(sender, SIGNAL(mutedChanged(bool)), SLOT(mutedChanged(bool))); + connect(sender, SIGNAL(outputDeviceChanged(const Phonon::AudioOutputDevice&)), SLOT(outputDeviceChanged(const Phonon::AudioOutputDevice&))); + connect(sender, SIGNAL(volumeChanged(qreal)), SLOT(volumeChanged(qreal))); +} + +void PhononAudioOutputSignalBridge::mutedChanged(bool muted) +{ + Q_UNUSED(muted) + // We probably don't have to handle this. We already get volumeChanged signals. + + //QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + // "audioOutput_mutedChanged", remoteId(), muted); +} + +void PhononAudioOutputSignalBridge::outputDeviceChanged(const Phonon::AudioOutputDevice &newAudioOutputDevice) +{ + Q_UNUSED(newAudioOutputDevice) + /// There's no matching signal in the private AudioOutput class. :-/ + + //QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + // "audioOutput_outputDeviceChanged", remoteId(), newAudioOutputDevice.index()); +} + +void PhononAudioOutputSignalBridge::volumeChanged(qreal newVolume) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(mApplication->socket(), QtSimulatorPrivate::NoSync, + "audioOutput_volumeChanged", remoteId(), newVolume); +} diff --git a/src/other/phononsignalbridges.h b/src/other/phononsignalbridges.h new file mode 100644 index 0000000..ab6a166 --- /dev/null +++ b/src/other/phononsignalbridges.h @@ -0,0 +1,113 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef __PHONONSIGNALBRIDGES_H__ +#define __PHONONSIGNALBRIDGES_H__ + +#include <phononsimulatorhelpers.h> +#include <phonon/mediaobject.h> +#include <phonon/audiooutput.h> + +using namespace Phonon; + +class Application; + +class PhononSignalBridge : public QObject +{ + Q_OBJECT +public: + PhononSignalBridge(Application* app, QObject* sender) + : QObject(sender), mApplication(app) + { + } + + inline Phonon::Simulator::Pointer remoteId() + { + Phonon::Simulator::Pointer p; + p.ptr = parent(); + return p; + } + +protected: + Application* mApplication; +}; + +class BackendSignalBridge : public PhononSignalBridge +{ + Q_OBJECT +public: + BackendSignalBridge(Application* app, QObject* sender); + +protected slots: + void on_backend_ObjectDescriptionChanged(ObjectDescriptionType); +}; + +class PhononMediaObjectSignalBridge : public PhononSignalBridge +{ + Q_OBJECT +public: + PhononMediaObjectSignalBridge(Application* app, QObject* sender); + + Phonon::MediaObject* mediaObject() + { + return qobject_cast<Phonon::MediaObject*>(parent()); + } + +private slots: + void aboutToFinish(); + void bufferStatus(int percentFilled); + void currentSourceChanged(const Phonon::MediaSource& newSource); + void finished(); + void hasVideoChanged(bool hasVideo); + void metaDataChanged(); + void prefinishMarkReached(qint32 msecToEnd); + void seekableChanged(bool isSeekable); + void stateChanged(Phonon::State newstate, Phonon::State oldstate); + void tick(qint64 time); + void totalTimeChanged(qint64 newTotalTime); +}; + +class PhononAudioOutputSignalBridge : public PhononSignalBridge +{ + Q_OBJECT +public: + PhononAudioOutputSignalBridge(Application* app, QObject* sender); + + Phonon::AudioOutput* audioOutput() + { + return qobject_cast<Phonon::AudioOutput*>(parent()); + } + +private slots: + void mutedChanged(bool muted); + void outputDeviceChanged(const Phonon::AudioOutputDevice &newAudioOutputDevice); + void volumeChanged(qreal newVolume); +}; + +#endif // __PHONONSIGNALBRIDGES_H__ diff --git a/src/other/phononvideowidget.cpp b/src/other/phononvideowidget.cpp new file mode 100644 index 0000000..f3367c8 --- /dev/null +++ b/src/other/phononvideowidget.cpp @@ -0,0 +1,51 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "phononvideowidget.h" +#include "application.h" +#include "displaywidget.h" +#include "widget.h" +#include "widgetmanager.h" +#include <phonon/videowidget.h> + +PhononVideoWidget::PhononVideoWidget(Application* app) +: QGraphicsProxyWidget(app->display()), + mApplication(app) +{ + connect(app, SIGNAL(destroyed()), this, SLOT(deleteLater())); + + mVideoWidget = new Phonon::VideoWidget; + setWidget(mVideoWidget); + + setData(0, QLatin1String("PhononVideoWidget")); +} + +PhononVideoWidget::~PhononVideoWidget() +{ +} diff --git a/src/other/phononvideowidget.h b/src/other/phononvideowidget.h new file mode 100644 index 0000000..8e0af97 --- /dev/null +++ b/src/other/phononvideowidget.h @@ -0,0 +1,61 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef __PHONONVIDEOWIDGET_H__ +#define __PHONONVIDEOWIDGET_H__ + +#include <QtGui/QGraphicsProxyWidget> + +class Application; +class Widget; + +namespace Phonon { + class VideoWidget; +} + +class PhononVideoWidget : public QGraphicsProxyWidget +{ + Q_OBJECT +public: + PhononVideoWidget(Application* app); + ~PhononVideoWidget(); + + Phonon::VideoWidget* videoWidget() const + { + return mVideoWidget; + } + +private slots: + +private: + Phonon::VideoWidget* mVideoWidget; + Application* mApplication; +}; + +#endif // __PHONONVIDEOWIDGET_H__ diff --git a/src/other/widget.cpp b/src/other/widget.cpp new file mode 100644 index 0000000..5beb814 --- /dev/null +++ b/src/other/widget.cpp @@ -0,0 +1,261 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "deviceitem.h" +#include "widget.h" +#include "application.h" +#include "displaywidget.h" +#include "qsimulatordata_p.h" + +#ifndef QT_NO_PHONON +#include "phononvideowidget.h" +#endif + +#include <QtCore/QDebug> +#include <QtCore/QSharedMemory> +#include <QtCore/QThread> +#include <QtCore/QTime> +#include <QtGui/QPainter> +#include <QtGui/QGraphicsSceneMouseEvent> +#include <QtGui/QGraphicsScene> + +class Sleeper : QThread +{ +public: + using QThread::msleep; +}; + +static int bytesForFormat(QImage::Format format) +{ + //qDebug() << "Size: " << (QImage(16,16, format).bytesPerLine() / 16); + return QImage(16,16, format).bytesPerLine() / 16; +} + +Widget::Widget(QRect geometry, QImage::Format f, const QString &t, Application* who, int id, QGraphicsItem *parent) + : QGraphicsItem(parent) + , format(f) + , widgetId(id) + , title(t) + , owner(who) + , memory(0) + , width(geometry.width()) + , height(geometry.height()) + , fullscreen(false) + , mMenuBar(0) + , wantsUpdate(false) +{ + //Commented out, in order to be + //able to easily re-enable mouse tracking + //setAcceptHoverEvents(true); + setFlag(QGraphicsItem::ItemIsFocusable); + setFlag(QGraphicsItem::ItemIgnoresParentOpacity); + setPos(geometry.topLeft()); + createMemory(); +} + +Widget::~Widget() +{ + scene()->removeItem(this); + delete memory; +} + +QRectF Widget::boundingRect() const +{ + return QRectF(0, 0, width, height); +} + +void Widget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + memory->lock(); + QImage image((uchar*)memory->data(), width, height, format); + painter->drawImage(QPoint(0,0), image); + memory->unlock(); +} + +bool Widget::createMemory() +{ + int size = width * height * bytesForFormat(format); + if (memory && size == memory->size()) + return true; + + if (memory) { + delete memory; + memory = 0; + } + + if (size < 0) + return false; + else if (size == 0) + size = 1; + + const QString key = QtSimulatorPrivate::qt_widgetShareName(owner->id(), widgetId); + //qDebug() << "Creating widget memory:" << size << key; + + memory = new QSharedMemory(key); + QTime time; + const int timeout = 1500; + while (!memory->create(size, QSharedMemory::ReadWrite)) { + if (memory->error() == QSharedMemory::AlreadyExists) + { + if (!memory->attach(QSharedMemory::ReadWrite)) + qFatal("Could not attach to existing shared memory, error %s", qPrintable(memory->errorString())); + if (memory->size() < size) + qFatal("Shared memory already exists, and is too small: %d where %d required", memory->size(), size); + break; + } + + if (time.isNull()) + time.start(); + else if (time.elapsed() >= timeout) { + qWarning() << "Could not create display memory."; + delete memory; + memory = 0; + return false; + } + else { + qWarning() << "Could not create display memory. Retrying..."; + Sleeper::msleep(10); + } + } + memory->lock(); + uchar* data = (uchar*) memory->data(); + QImage displayImage(data, width, height, format); + QPainter imagePainter(&displayImage); + QBrush brush(Qt::transparent); + imagePainter.fillRect(0,0, width, height, brush); + imagePainter.end(); + memory->unlock(); + return true; +} + +QRect Widget::geometry() const +{ + return QRect(x(), y(), width, height); +} + +void Widget::setGeometry(QRect g) +{ + prepareGeometryChange(); + setPos(g.topLeft()); + width = g.width(); + height = g.height(); + createMemory(); +} + +void Widget::mousePressEvent(QGraphicsSceneMouseEvent* ev) +{ + handleMouseEvent(QEvent::MouseButtonPress, ev); +} + +void Widget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev) +{ + handleMouseEvent(QEvent::MouseButtonDblClick, ev); +} + +void Widget::mouseReleaseEvent(QGraphicsSceneMouseEvent* ev) +{ + handleMouseEvent(QEvent::MouseButtonRelease, ev); +} + +void Widget::mouseMoveEvent(QGraphicsSceneMouseEvent* ev) +{ + handleMouseEvent(QEvent::MouseMove, ev); +} + +void Widget::hoverMoveEvent(QGraphicsSceneHoverEvent *ev) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, + "dispatchMouseEvent", + widgetId, + static_cast<int>(QEvent::MouseMove), + mapToItem(owner->display(), ev->pos() - offset).toPoint(), + static_cast<int>(Qt::NoButton), + static_cast<int>(Qt::NoButton), + static_cast<int>(ev->modifiers())); + ev->accept(); +} + +void Widget::handleMouseEvent(QEvent::Type type, QGraphicsSceneMouseEvent *ev) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, + "dispatchMouseEvent", + widgetId, + static_cast<int>(type), + mapToItem(owner->display(), ev->pos() - offset).toPoint(), + static_cast<int>(ev->button()), + static_cast<int>(ev->buttons()), + static_cast<int>(ev->modifiers())); + ev->accept(); +} + +void Widget::keyPressEvent(QKeyEvent* ev) +{ + handleKeyEvent(ev); +} + +void Widget::keyReleaseEvent(QKeyEvent* ev) +{ + handleKeyEvent(ev); +} + +void Widget::handleKeyEvent(QKeyEvent* ev) +{ + QtSimulatorPrivate::RemoteMetacall<void>::call(owner->socket(), QtSimulatorPrivate::NoSync, + "dispatchKeyEvent", + widgetId, + static_cast<int>(ev->type()), + static_cast<int>(ev->key()), + static_cast<int>(ev->modifiers()), + ev->text(), + ev->isAutoRepeat(), + static_cast<int>(ev->count())); + ev->accept(); +} + +void Widget::updateOffset(const QPoint &newOffset) +{ + if (offset != newOffset) { + setPos(pos() - offset + newOffset); + + offset = newOffset; + } +} + +void Widget::setFullscreen(bool full) +{ + fullscreen = full; +} + +bool Widget::isFullScreen() const +{ + return fullscreen; +} diff --git a/src/other/widget.h b/src/other/widget.h new file mode 100644 index 0000000..cbe82d5 --- /dev/null +++ b/src/other/widget.h @@ -0,0 +1,93 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef WIDGET_H +#define WIDGET_H + +#include <QtGui/QGraphicsItem> +#include <QtGui/QtEvents> + +class Application; +class QSharedMemory; +class QString; +class QMenuBar; + +class Widget : public QGraphicsItem +{ +public: + Widget(QRect geometry, QImage::Format f, const QString &t, Application* who, int id, QGraphicsItem *parent=0); + ~Widget(); + + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0); + + static const int WidgetType = UserType+1; + virtual int type() const { return WidgetType; } + + bool createMemory(); + QImage::Format format; + int widgetId; + QString title; + Application* owner; + + QRect geometry() const; + void setGeometry(QRect g); + + void updateOffset(const QPoint &newOffset); + void setFullscreen(bool full); + bool isFullScreen() const; + + QMenuBar* menuBar() const { return mMenuBar; } + void setMenuBar(QMenuBar* menuBar) { mMenuBar = menuBar; } + +protected: + virtual void mousePressEvent(QGraphicsSceneMouseEvent* ev); + virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* ev); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent* ev); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* ev); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* ev); + virtual void keyPressEvent(QKeyEvent* ev); + virtual void keyReleaseEvent(QKeyEvent* ev); + void handleMouseEvent(QEvent::Type type, QGraphicsSceneMouseEvent* ev); + void handleKeyEvent(QKeyEvent* ev); + +private: + friend class WidgetManager; + friend class DisplayWidget; + QSharedMemory *memory; + + int width; + int height; + QPoint offset; + bool fullscreen; + QMenuBar* mMenuBar; + bool wantsUpdate; +}; + +#endif // WIDGET_H diff --git a/src/other/widgetmanager.cpp b/src/other/widgetmanager.cpp new file mode 100644 index 0000000..0d4fb37 --- /dev/null +++ b/src/other/widgetmanager.cpp @@ -0,0 +1,536 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "widgetmanager.h" +#include "widget.h" +#include "menuwidget.h" +#include "application.h" +#include "displaywidget.h" +#include "qsimulatordata_p.h" + +#include <QtCore/QDebug> +#include <QtGui/QWidget> +#include <QtGui/QTableWidget> +#include <QtGui/QLayout> + +namespace { + int gWidgetIdCounter = 100; // 0 is the desktop. +} + +inline QString stringForCoord(QRect geometry) +{ + QString result; + result += QString::number(geometry.left()) + QLatin1String(",") + QString::number(geometry.top()) + QLatin1String(";"); + result += QString::number(geometry.width()) + QLatin1String(",") + QString::number(geometry.height()); + return result; +} + +WidgetManager::WidgetManager(DisplayWidget *dw, QObject *parent) + : QObject(parent) + , displayWidget(dw) + , mFocusWidget(0) +{ + // Some client applications repaint themselves continuously and send an inordinate amount + // of paint events. If we call update for every one of these, the event loop stalls on unix + // and no timers get executed any more. So we just store the update request + // (Widget::wantsUpdate) and handle them regularly. + QTimer *updateTimer = new QTimer(this); + connect(updateTimer, SIGNAL(timeout()), this, SLOT(handleUpdateRequests())); + updateTimer->start(1000/60); + mImageFormat = QImage::Format_RGB32; + + tableWidget = new QTableWidget(0, 3); + QStringList headerItems; + headerItems << "ID" << "Widget Name" << "Rect"; + tableWidget->setHorizontalHeaderLabels(headerItems); + configWidget = new QWidget(); + QHBoxLayout* layout = new QHBoxLayout; + layout->addWidget(tableWidget); + configWidget->setLayout(layout); +} + +WidgetManager::~WidgetManager() +{ +} + +DisplayWidget* WidgetManager::display() const +{ + return displayWidget; +} + +QImage::Format WidgetManager::imageFormat() const +{ + return mImageFormat; +} + +// Returns the widget with the given id, asserts if not found. +Widget* WidgetManager::widgetForId(int id) const +{ + // ignore requests for the root widget + if (id == 0 || id == SIMULATOR_DISPLAY_ID) + return 0; + + foreach(Widget* w, widgets) { + if (w->widgetId == id) + return w; + } + Q_ASSERT(false && "widgetId does not exist"); + return 0; +} + +int WidgetManager::widgetAt(const QPoint &p) const +{ + QPoint actualPosition = p + mOffset; + //qDebug("WidgetManager::idForPosition %d, %d", p.x(), p.y()); + foreach(Widget* w, widgets) { + if (!w->isVisible()) + continue; + const QPoint t(w->parentItem()->mapFromItem(displayWidget, actualPosition).toPoint()); + const QRect wGeometry = w->geometry(); + if (wGeometry.contains(t)) + return w->widgetId; + } + return 0; +} + +Widget *WidgetManager::focusWidget() const +{ + return mFocusWidget; +} + +Widget *WidgetManager::activeWidget() const +{ + if (mFocusWidget) + return mFocusWidget; + + else return topWidget(); +} + +Widget *WidgetManager::topWidget() const +{ + Widget *top = 0; + foreach(Widget* w, widgets) { + if (!top || w->zValue() > top->zValue()) { + top = w; + continue; + } + } + return top; +} + +int WidgetManager::create(int parentWidgetId, QRect geometry, const QString &title, Application* app) +{ + //qDebug() << "Creating Widget... parent: " << parentWidgetId << " geometry: " << geometry << " id: " << gWidgetIdCounter; + + QGraphicsItem *parent = displayWidget; + if (parentWidgetId) + parent = widgetForId(parentWidgetId); + if (!parent) + qFatal("Could not create child widget of unknown parent with id %d", parentWidgetId); + + geometry = QRect(parent->mapFromItem(displayWidget, geometry.topLeft() + mOffset).toPoint(), geometry.size()); + Widget *w = new Widget(geometry, mImageFormat, title, app, gWidgetIdCounter++, parent); + w->hide(); + w->offset = mOffset; + + widgets.push_front(w); + setHighestZ(w); + + // insert into debug window widgets list + tableWidget->insertRow(0); + tableWidget->setItem(0, 0, new QTableWidgetItem(QString::number(w->widgetId))); + tableWidget->setItem(0, 1, new QTableWidgetItem(w->title)); + tableWidget->setItem(0, 2, new QTableWidgetItem(stringForCoord(w->geometry()))); + + return w->widgetId; +} + +void WidgetManager::showWidget(int id) +{ + //qDebug("WidgetManager::show %d", id); + Widget* w = widgetForId(id); + if (!w) + return; + w->show(); + w->update(); + w->setFocus(); + updateLogItem(id); +} + +void WidgetManager::paintWidget(qint32 id) +{ + Widget* w = widgetForId(id); + if (!w) + return; + + w->wantsUpdate = true; +} + +void WidgetManager::setWidgetGeometry(int id, const QRect &geometry) +{ + //qDebug() << "WidgetManager::setGeometry " << id << " geometry: " << geometry; + Widget *w = widgetForId(id); + if (!w) + return; + + QRect transformed(geometry); + transformed.moveTopLeft(w->parentItem()->mapFromItem(displayWidget, transformed.topLeft() + mOffset).toPoint()); + w->setGeometry(transformed); + + if (!w->createMemory()) + qFatal("Could not create memory for widget."); + updateLogItem(id); +} + +void WidgetManager::moveWidget(int id, const QPoint &to) +{ + Widget *w = widgetForId(id); + if (!w) + return; + + QPoint p; + p = QPoint(w->parentItem()->mapFromItem(displayWidget, to + mOffset).toPoint()); + w->setPos(p); + + updateLogItem(id); +} + +void WidgetManager::updateLogItem(int id) +{ + // Find the list item + int row = -1; + for (int i = 0; i < tableWidget->rowCount(); ++i) { + if (tableWidget->item(i,0)->text().toInt() == id) { + row = i; + break; + } + } + // Find the widget + Widget *w = 0; + for (int i = 0; i < widgets.size(); ++i) { + if (widgets.at(i)->widgetId == id) { + w = widgets.at(i); + break; + } + } + + if (row == -1 || w == 0) + return; + + // update the content + tableWidget->setItem(row, 0, new QTableWidgetItem(QString::number(w->widgetId))); + tableWidget->setItem(row, 1, new QTableWidgetItem(w->title)); + QRect actualGeometry = w->geometry(); + actualGeometry.adjust(-mOffset.x(), -mOffset.y(), 0, 0); + tableWidget->setItem(row, 2, new QTableWidgetItem(stringForCoord(actualGeometry) + QString(";z:") + QString::number(w->zValue()))); +} + +void WidgetManager::hideWidget(int id) +{ + Widget *w = widgetForId(id); + if (!w) + return; + w->hide(); +} + +void WidgetManager::destroyWidget(int id) +{ + Widget *w = widgetForId(id); + if (!w) + return; + removeWidgetFromTable(id); + widgets.removeAll(w); + if (mFocusWidget == w) { + mFocusWidget = topWidget(); + if (mFocusWidget) + emit topWidgetChanged(mFocusWidget); + else + emit topWidgetChanged(0); + } + delete w; +} + +void WidgetManager::raiseAboveMenus(int id) +{ + Widget *w = widgetForId(id); + if (!w) + return; + w->setFullscreen(true); + setHighestZ(w); +} + +void WidgetManager::dropBelowMenus(int id) +{ + Widget *w = widgetForId(id); + if (!w) + return; + w->setFullscreen(false); + setHighestZ(w); +} + +void WidgetManager::removeWidgetFromTable(int id) +{ + // Find the list item + int row = -1; + for (int i = 0; i < tableWidget->rowCount(); ++i) { + if (tableWidget->item(i,0)->text().toInt() == id) { + row = i; + break; + } + } + if (row != -1) + tableWidget->removeRow(row); +} + +void WidgetManager::onApplicationUnregistered(int appId) +{ + for (int i =0; i < widgets.length(); i++) { + Widget *current = widgets.at(i); + if (current->owner->id() == appId) { + destroyWidget(current->widgetId); + --i; + } + } +} + +void WidgetManager::stackWidget(int id, int pos) +{ + //qDebug("WidgetManager::stack %d %d", id, pos); + Widget *item = widgetForId(id); + if (!item) + return; + + if (pos == -1) { // -1 front + setHighestZ(item); + } else if (pos == -2) { // -2 back + setLowestZ(item); + } else if (pos > 0) { + Widget *under = widgetForId(pos); + if (!under) + return; + + setZBefore(item, under); + } +} + +void WidgetManager::setWidgetWindowTitle(int id, const QString &title) +{ + Widget *w = widgetForId(id); + if (!w) + return; + w->title = title; + // ### TODO: Update the window decorations when they exist. +} + +void WidgetManager::setFocusWidget(int id) +{ + Widget *w = widgetForId(id); + if (!w) + return; + mFocusWidget = w; + mFocusWidget->setFocus(); +} + +void WidgetManager::setWidgetOpacity(int id, double opacity) +{ + Widget *w = widgetForId(id); + if (!w) + return; + w->setOpacity(opacity); +} + +void WidgetManager::setWidgetParent(int id, int newParentId) +{ + Widget *w = widgetForId(id); + if (!w) + return; + Widget *newParent = widgetForId(newParentId); + if (!newParent) + return; + + //qDebug() << "Setting parent for " << id << " to " << newParentId; + w->setParentItem(newParent); +} + +void WidgetManager::handleUpdateRequests() +{ + foreach (Widget *w, widgets) { + if (w->isVisible() && w->wantsUpdate) { + w->update(); + w->wantsUpdate = false; + } + } +} + +void WidgetManager::sendKeyPress(Qt::Key key, const QString &text) +{ + Widget *fw = focusWidget(); + if (!fw) + return; + + QScopedPointer<QKeyEvent> ev(new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, text)); + fw->handleKeyEvent(ev.data()); +} + +void WidgetManager::sendKeyRelease(Qt::Key key) +{ + // BUG: Can we be certain the focus widget didn't change since the key press? + Widget *fw = focusWidget(); + if (!fw) + return; + + QScopedPointer<QKeyEvent> ev(new QKeyEvent(QEvent::KeyRelease, key, Qt::NoModifier)); + fw->handleKeyEvent(ev.data()); +} + +void WidgetManager::changeOffset(const QPoint &offset) +{ + mOffset = offset; + updateWidgetOffset(mOffset); +} + +void WidgetManager::updateWidgetOffset(const QPoint &newOffset) +{ + foreach(Widget* w, widgets) { + w->updateOffset(newOffset); + } +} + + +/*! + Adjust the Z order of this and all siblings to make this have the highest value + and thus be painted over all siblings. +*/ +void WidgetManager::setHighestZ(Widget *w) +{ + if (!w->parentItem()) + return; + + QMap<qreal, Widget *> order; + + // get the existing z order of everything but this and menus + foreach (Widget *child, widgets) { + if (child != w && child->type() != MenuWidget::MenuType + && w->isFullScreen() == child->isFullScreen()) + order.insert(child->zValue(), child); + } + + int z; + // set new z order with this on top + if (!w->isFullScreen()) + z = 0; + else + z = SIMULATOR_MENU_Z + 1; + foreach (Widget *v, order) + v->setZValue(z++); + w->setZValue(z); + + // show the active menu bar + emit topWidgetChanged(w); + +#ifndef QT_NO_PHONON + // make sure that video widgets stay on top + ++z; + foreach (Widget *child, widgets) { + QVariant objectName = child->data(0); + if (objectName.isNull() || objectName.toString() != QLatin1String("PhononVideoWidget")) + continue; + + child->setZValue(z); + } +#endif +} + +/*! + Adjust the Z order of this and all siblings to make this have the lowest value + and thus be painted under all siblings. +*/ +void WidgetManager::setLowestZ(Widget *w) +{ + if (!w->parentItem()) + return; + + QMap<qreal, Widget *> order; + + // get the existing z order of everything but this and menus + foreach (Widget *child, widgets) { + if (child != w && child->type() != MenuWidget::MenuType + && w->isFullScreen() == child->isFullScreen()) + order.insert(child->zValue(), child); + } + + int z; + if (!w->isFullScreen()) + z = 0; + else + z = SIMULATOR_MENU_Z + 1; + + w->setZValue(z++); + foreach (Widget *v, order) + v->setZValue(z++); +} + +/*! + Adjust the Z order of this and all siblings to make this be painted just before other. +*/ +void WidgetManager::setZBefore(Widget *w, Widget *other) +{ + if (!w->parentItem()) + return; + + QMap<qreal, Widget *> order; + bool otherFound = false; + + // get the existing z order of everything but this and menus + foreach (Widget *child, widgets) { + if (child != w && child->type() != MenuWidget::MenuType) + order.insert(child->zValue(), child); + if (child == other) + otherFound = true; + } + if (!otherFound) { + qWarning("Could not reorder widgets. %s is no sibling of %s", + qPrintable(other->title), qPrintable(w->title)); + return; + } + + // set new z order with this before other + int z; + if (other->isFullScreen()) + z = SIMULATOR_MENU_Z + 1; + else + z = 0; + foreach (Widget *v, order) { + if (v->isFullScreen() == other->isFullScreen()) { + if (v == other) + w->setZValue(z++); + v->setZValue(z++); + } + } +} diff --git a/src/other/widgetmanager.h b/src/other/widgetmanager.h new file mode 100644 index 0000000..185bb21 --- /dev/null +++ b/src/other/widgetmanager.h @@ -0,0 +1,109 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef WIDGETMANAGER_H +#define WIDGETMANAGER_H + +#include <QtGui/QImage> +#include <QtCore/QObject> + +class Application; +class DisplayWidget; +class Widget; +class QPoint; +class QRect; +class QTableWidget; +class QWidget; +class QMenuBar; + +class WidgetManager : public QObject +{ + Q_OBJECT +public: + explicit WidgetManager(DisplayWidget *dw, QObject *parent = 0); + ~WidgetManager(); + + Widget* widgetForId(int) const; + Widget* focusWidget() const; + Widget* activeWidget() const; + Widget* topWidget() const; + + DisplayWidget* display() const; + QImage::Format imageFormat() const; + inline QWidget* logWidget() { return configWidget; } + + int create(int parentWidgetId, QRect geometry, const QString &title, Application *app); + +public slots: + int widgetAt(const QPoint &position) const; + void showWidget(int); + void paintWidget(int id); + void setWidgetGeometry(int id, const QRect &geometry); + void moveWidget(int id, const QPoint &to); + void hideWidget(int id); + void destroyWidget(int id); + void raiseAboveMenus(int id); + void dropBelowMenus(int id); + void stackWidget(int id, int pos); // -1 front, -2 back + void setHighestZ(Widget *w); + void setLowestZ(Widget *w); + void setZBefore(Widget *w, Widget *other); + void setWidgetWindowTitle(int id, const QString &title); + void setFocusWidget(int id); + void setWidgetOpacity(int id, double opacity); + void setWidgetParent(int id, int newParentId); + + void onApplicationUnregistered(int appId); + + void sendKeyPress(Qt::Key key, const QString &text = ""); + void sendKeyRelease(Qt::Key key); + + void changeOffset(const QPoint &offset); + + private slots: + void handleUpdateRequests(); + +signals: + void topWidgetChanged(Widget *); + +private: + void updateLogItem(int id); + void removeWidgetFromTable(int id); + void updateWidgetOffset(const QPoint &newOffset); + QList<Widget*> widgets; + QTableWidget *tableWidget; + QWidget *configWidget; + DisplayWidget *displayWidget; + Widget *mFocusWidget; + QPoint mOffset; + + QImage::Format mImageFormat; +}; + +#endif diff --git a/src/shared/qtlockedfile/README.txt b/src/shared/qtlockedfile/README.txt new file mode 100644 index 0000000..6fcf2fd --- /dev/null +++ b/src/shared/qtlockedfile/README.txt @@ -0,0 +1,10 @@ +This is the src directory of the QtLockedFile +solution integrated over from addons/main/utils/qtlockedfile/src . + +namespace.patch was applied to introduce the SharedTools namespace. + +It is required by the QtSingleApplication solution. + +History: + +16.05.2008 Integrated diff --git a/src/shared/qtlockedfile/namespace.patch b/src/shared/qtlockedfile/namespace.patch new file mode 100644 index 0000000..eb894a3 --- /dev/null +++ b/src/shared/qtlockedfile/namespace.patch @@ -0,0 +1,70 @@ + +--- qtlockedfile.cpp 1970-01-01 01:00:00.000000000 ++++ qtlockedfile.cpp 2008/05/16 10:51:19.000000000 +@@ -1,5 +1,7 @@ + #include "qtlockedfile.h" + ++namespace SharedTools { ++ + /*! + \class QtLockedFile + +@@ -123,3 +125,5 @@ + + Destroys the \e QtLockedFile object. If any locks were held, they are released. + */ ++ ++} + +--- qtlockedfile.h 1970-01-01 01:00:00.000000000 ++++ qtlockedfile.h 2008/05/16 10:51:19.000000000 +@@ -19,6 +19,8 @@ + # define QT_QTLOCKEDFILE_EXPORT + #endif + ++namespace SharedTools { ++ + class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile + { + public: +@@ -41,4 +43,6 @@ + LockMode m_lock_mode; + }; + ++} ++ + #endif + +--- qtlockedfile_unix.cpp 1970-01-01 01:00:00.000000000 ++++ qtlockedfile_unix.cpp 2008/05/16 10:51:19.000000000 +@@ -5,6 +5,8 @@ + + #include "qtlockedfile.h" + ++namespace SharedTools { ++ + bool QtLockedFile::lock(LockMode mode, bool block) + { + if (!isOpen()) { +@@ -73,3 +75,4 @@ + unlock(); + } + ++} + +--- qtlockedfile_win.cpp 1970-01-01 01:00:00.000000000 ++++ qtlockedfile_win.cpp 2008/05/16 10:51:19.000000000 +@@ -2,6 +2,8 @@ + #include <qt_windows.h> + #include <QtCore/QFileInfo> + ++namespace SharedTools { ++ + #define SEMAPHORE_PREFIX "QtLockedFile semaphore " + #define MUTEX_PREFIX "QtLockedFile mutex " + #define SEMAPHORE_MAX 100 +@@ -168,3 +170,4 @@ + } + } + ++} diff --git a/src/shared/qtlockedfile/qtlockedfile.cpp b/src/shared/qtlockedfile/qtlockedfile.cpp new file mode 100644 index 0000000..9277510 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile.cpp @@ -0,0 +1,158 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtlockedfile.h" + +namespace SharedTools { + +/*! + \class QtLockedFile + + \brief The QtLockedFile class extends QFile with advisory locking functions. + + A file may be locked in read or write mode. Multiple instances of + \e QtLockedFile, created in multiple processes running on the same + machine, may have a file locked in read mode. Exactly one instance + may have it locked in write mode. A read and a write lock cannot + exist simultaneously on the same file. + + The file locks are advisory. This means that nothing prevents + another process from manipulating a locked file using QFile or + file system functions offered by the OS. Serialization is only + guaranteed if all processes that access the file use + QtLockedFile. Also, while holding a lock on a file, a process + must not open the same file again (through any API), or locks + can be unexpectedly lost. + + The lock provided by an instance of \e QtLockedFile is released + whenever the program terminates. This is true even when the + program crashes and no destructors are called. +*/ + +/*! \enum QtLockedFile::LockMode + + This enum describes the available lock modes. + + \value ReadLock A read lock. + \value WriteLock A write lock. + \value NoLock Neither a read lock nor a write lock. +*/ + +/*! + Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way + as \e QFile::QFile(). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile() + : QFile() +{ +#ifdef Q_OS_WIN + m_semaphore_hnd = 0; + m_mutex_hnd = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in + the same way as \e QFile::QFile(const QString&). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile(const QString &name) + : QFile(name) +{ +#ifdef Q_OS_WIN + m_semaphore_hnd = 0; + m_mutex_hnd = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Returns \e true if this object has a in read or write lock; + otherwise returns \e false. + + \sa lockMode() +*/ +bool QtLockedFile::isLocked() const +{ + return m_lock_mode != NoLock; +} + +/*! + Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. + + \sa isLocked() +*/ +QtLockedFile::LockMode QtLockedFile::lockMode() const +{ + return m_lock_mode; +} + +/*! + \fn bool QtLockedFile::lock(LockMode mode, bool block = true) + + Obtains a lock of type \a mode. + + If \a block is true, this + function will block until the lock is acquired. If \a block is + false, this function returns \e false immediately if the lock cannot + be acquired. + + If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock + is first released and then a new lock is obtained. + + This function returns \e true if, after it executes, the file is locked by this object, + and \e false otherwise. + + \sa unlock(), isLocked(), lockMode() +*/ + +/*! + \fn bool QtLockedFile::unlock() + + Releases a lock. + + If the object has no lock, this function returns immediately. + + This function returns \e true if, after it executes, the file is not locked by + this object, and \e false otherwise. + + \sa lock(), isLocked(), lockMode() +*/ + +/*! + \fn QtLockedFile::~QtLockedFile() + + Destroys the \e QtLockedFile object. If any locks were held, they are released. +*/ + +} // namespace SharedTools diff --git a/src/shared/qtlockedfile/qtlockedfile.h b/src/shared/qtlockedfile/qtlockedfile.h new file mode 100644 index 0000000..1a438e7 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile.h @@ -0,0 +1,77 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QTLOCKEDFILE_H +#define QTLOCKEDFILE_H + +#include <QtCore/QFile> + +#if defined(Q_OS_WIN) +# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) +# define QT_QTLOCKEDFILE_EXPORT +# elif defined(QT_QTLOCKEDFILE_IMPORT) +# if defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# endif +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) +# elif defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTLOCKEDFILE_EXPORT +#endif + +namespace SharedTools { + +class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile +{ +public: + enum LockMode { NoLock = 0, ReadLock, WriteLock }; + + QtLockedFile(); + QtLockedFile(const QString &name); + ~QtLockedFile(); + + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; + +private: +#ifdef Q_OS_WIN + Qt::HANDLE m_semaphore_hnd; + Qt::HANDLE m_mutex_hnd; +#endif + LockMode m_lock_mode; +}; + +} // namespace SharedTools + +#endif // QTLOCKEDFILE_H diff --git a/src/shared/qtlockedfile/qtlockedfile.pri b/src/shared/qtlockedfile/qtlockedfile.pri new file mode 100644 index 0000000..46d1f1a --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile.pri @@ -0,0 +1,13 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +HEADERS += $$PWD/qtlockedfile.h +SOURCES += $$PWD/qtlockedfile.cpp + +unix:SOURCES += $$PWD/qtlockedfile_unix.cpp +win32:SOURCES += $$PWD/qtlockedfile_win.cpp + +win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + DEFINES += QT_QTLOCKEDFILE_EXPORT=__declspec(dllexport) +} + + diff --git a/src/shared/qtlockedfile/qtlockedfile_unix.cpp b/src/shared/qtlockedfile/qtlockedfile_unix.cpp new file mode 100644 index 0000000..76eb151 --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile_unix.cpp @@ -0,0 +1,107 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtlockedfile.h" + +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +namespace SharedTools { + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); + + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + + m_lock_mode = mode; + return true; +} + + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_UNLCK; + int ret = fcntl(handle(), F_SETLKW, &fl); + + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + m_lock_mode = NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); +} + +} // namespace SharedTools diff --git a/src/shared/qtlockedfile/qtlockedfile_win.cpp b/src/shared/qtlockedfile/qtlockedfile_win.cpp new file mode 100644 index 0000000..758055f --- /dev/null +++ b/src/shared/qtlockedfile/qtlockedfile_win.cpp @@ -0,0 +1,203 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtlockedfile.h" + +#include <qt_windows.h> +#include <QtCore/QFileInfo> + +namespace SharedTools { + +#define SEMAPHORE_PREFIX "QtLockedFile semaphore " +#define MUTEX_PREFIX "QtLockedFile mutex " +#define SEMAPHORE_MAX 100 + +static QString errorCodeToString(DWORD errorCode) +{ + QString result; + char *data = 0; + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + 0, errorCode, 0, + (char*)&data, 0, 0); + result = QString::fromLocal8Bit(data); + if (data != 0) + LocalFree(data); + + if (result.endsWith("\n")) + result.truncate(result.length() - 1); + + return result; +} + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != 0) + unlock(); + + if (m_semaphore_hnd == 0) { + QFileInfo fi(*this); + QString sem_name = QString::fromLatin1(SEMAPHORE_PREFIX) + + fi.absoluteFilePath().toLower(); + + QT_WA( { + m_semaphore_hnd = CreateSemaphoreW(0, SEMAPHORE_MAX, SEMAPHORE_MAX, + (TCHAR*)sem_name.utf16()); + } , { + m_semaphore_hnd = CreateSemaphoreA(0, SEMAPHORE_MAX, SEMAPHORE_MAX, + sem_name.toLocal8Bit().constData()); + } ); + + if (m_semaphore_hnd == 0) { + qWarning("QtLockedFile::lock(): CreateSemaphore: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + } + + bool gotMutex = false; + int decrement; + if (mode == ReadLock) { + decrement = 1; + } else { + decrement = SEMAPHORE_MAX; + if (m_mutex_hnd == 0) { + QFileInfo fi(*this); + QString mut_name = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + QT_WA( { + m_mutex_hnd = CreateMutexW(NULL, FALSE, (TCHAR*)mut_name.utf16()); + } , { + m_mutex_hnd = CreateMutexA(NULL, FALSE, mut_name.toLocal8Bit().constData()); + } ); + + if (m_mutex_hnd == 0) { + qWarning("QtLockedFile::lock(): CreateMutex: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + } + DWORD res = WaitForSingleObject(m_mutex_hnd, block ? INFINITE : 0); + if (res == WAIT_TIMEOUT) + return false; + if (res == WAIT_FAILED) { + qWarning("QtLockedFile::lock(): WaitForSingleObject (mutex): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + gotMutex = true; + } + + for (int i = 0; i < decrement; ++i) { + DWORD res = WaitForSingleObject(m_semaphore_hnd, block ? INFINITE : 0); + if (res == WAIT_TIMEOUT) { + if (i) { + // A failed nonblocking rw locking. Undo changes to semaphore. + if (ReleaseSemaphore(m_semaphore_hnd, i, NULL) == 0) { + qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + // Fall through + } + } + if (gotMutex) + ReleaseMutex(m_mutex_hnd); + return false; + } + if (res != WAIT_OBJECT_0) { + if (gotMutex) + ReleaseMutex(m_mutex_hnd); + qWarning("QtLockedFile::lock(): WaitForSingleObject (semaphore): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + } + + m_lock_mode = mode; + if (gotMutex) + ReleaseMutex(m_mutex_hnd); + return true; +} + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + int increment; + if (m_lock_mode == ReadLock) + increment = 1; + else + increment = SEMAPHORE_MAX; + + DWORD ret = ReleaseSemaphore(m_semaphore_hnd, increment, 0); + if (ret == 0) { + qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + return false; + } + + m_lock_mode = QtLockedFile::NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); + if (m_mutex_hnd != 0) { + DWORD ret = CloseHandle(m_mutex_hnd); + if (ret == 0) { + qWarning("QtLockedFile::~QtLockedFile(): CloseHandle (mutex): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + } + m_mutex_hnd = 0; + } + if (m_semaphore_hnd != 0) { + DWORD ret = CloseHandle(m_semaphore_hnd); + if (ret == 0) { + qWarning("QtLockedFile::~QtLockedFile(): CloseHandle (semaphore): %s", + errorCodeToString(GetLastError()).toLatin1().constData()); + } + m_semaphore_hnd = 0; + } +} + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/README.txt b/src/shared/qtsingleapplication/README.txt new file mode 100644 index 0000000..1909a33 --- /dev/null +++ b/src/shared/qtsingleapplication/README.txt @@ -0,0 +1,10 @@ +This is the src directory of the QtSingleApplication solution +integrated over from addons/main/utils/qtsingleapplication/src . + +namespace.patch was applied to introduce the SharedTools namespace. + +It additionally requires the QtLockedFile solution. + +History: + +16.05.2008 Integrated diff --git a/src/shared/qtsingleapplication/namespace.patch b/src/shared/qtsingleapplication/namespace.patch new file mode 100644 index 0000000..2876e3a --- /dev/null +++ b/src/shared/qtsingleapplication/namespace.patch @@ -0,0 +1,133 @@ + +--- qtlocalpeer.cpp 1970-01-01 01:00:00.000000000 ++++ qtlocalpeer.cpp 2008/05/16 10:36:53.000000000 +@@ -13,6 +13,8 @@ + #include <time.h> + #endif + ++namespace SharedTools { ++ + const char* QtLocalPeer::ack = "ack"; + + QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) +@@ -139,3 +141,5 @@ + delete socket; + emit messageReceived(message); // ##(might take a long time to return) + } ++ ++} + +--- qtlocalpeer.h 1970-01-01 01:00:00.000000000 ++++ qtlocalpeer.h 2008/05/16 10:36:53.000000000 +@@ -1,9 +1,11 @@ + ++ + #include <QtNetwork/QLocalServer> + #include <QtNetwork/QLocalSocket> + #include <QtCore/QDir> + #include <qtlockedfile.h> + ++namespace SharedTools { + + class QtLocalPeer : public QObject + { +@@ -31,3 +33,5 @@ + private: + static const char* ack; + }; ++ ++} // SharedTools + +--- qtsingleapplication.cpp 1970-01-01 01:00:00.000000000 ++++ qtsingleapplication.cpp 2008/05/16 10:36:53.000000000 +@@ -3,6 +3,8 @@ + #include "qtlocalpeer.h" + #include <QtGui/QWidget> + ++namespace SharedTools { ++ + void QtSingleApplication::sysInit(const QString &appId) + { + actWin = 0; +@@ -95,3 +97,5 @@ + actWin->activateWindow(); + } + } ++ ++} + +--- qtsingleapplication.h 1970-01-01 01:00:00.000000000 ++++ qtsingleapplication.h 2008/05/16 10:36:53.000000000 +@@ -1,6 +1,8 @@ + + #include <QtGui/QApplication> + ++namespace SharedTools { ++ + class QtLocalPeer; + + class QtSingleApplication : public QApplication +@@ -47,3 +49,5 @@ + QtLocalPeer *peer; + QWidget *actWin; + }; ++ ++} + +--- qtsingleapplication.pri 1970-01-01 01:00:00.000000000 ++++ qtsingleapplication.pri 2008/05/16 10:36:53.000000000 +@@ -6,7 +6,7 @@ + QT *= network + + gotqtlockedfile = $$find(HEADERS, .*qtlockedfile.h) +-isEmpty(gotqtlockedfile):include(../../qtlockedfile/src/qtlockedfile.pri) ++isEmpty(gotqtlockedfile):include(../qtlockedfile/qtlockedfile.pri) + + + win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + +--- qtsinglecoreapplication.cpp 1970-01-01 01:00:00.000000000 ++++ qtsinglecoreapplication.cpp 2008/05/16 10:36:53.000000000 +@@ -2,6 +2,7 @@ + #include "qtsinglecoreapplication.h" + #include "qtlocalpeer.h" + ++namespace SharedTools { + + QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) + : QCoreApplication(argc, argv) +@@ -36,3 +37,4 @@ + return peer->applicationId(); + } + ++} + +--- qtsinglecoreapplication.h 1970-01-01 01:00:00.000000000 ++++ qtsinglecoreapplication.h 2008/05/16 10:36:53.000000000 +@@ -1,6 +1,8 @@ + + #include <QtCore/QCoreApplication> + ++namespace SharedTools { ++ + class QtLocalPeer; + + class QtSingleCoreApplication : public QCoreApplication +@@ -25,3 +27,5 @@ + private: + QtLocalPeer* peer; + }; ++ ++} + +--- qtsinglecoreapplication.pri 1970-01-01 01:00:00.000000000 ++++ qtsinglecoreapplication.pri 2008/05/16 10:36:53.000000000 +@@ -6,7 +6,7 @@ + QT *= network + + gotqtlockedfile = $$find(HEADERS, .*qtlockedfile.h) +-isEmpty(gotqtlockedfile):include(../../qtlockedfile/src/qtlockedfile.pri) ++isEmpty(gotqtlockedfile):include(../qtlockedfile/qtlockedfile.pri) + + + win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { diff --git a/src/shared/qtsingleapplication/qtlocalpeer.cpp b/src/shared/qtsingleapplication/qtlocalpeer.cpp new file mode 100644 index 0000000..45b130c --- /dev/null +++ b/src/shared/qtsingleapplication/qtlocalpeer.cpp @@ -0,0 +1,172 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtlocalpeer.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QTime> + +#if defined(Q_OS_WIN) +#include <QtCore/QLibrary> +#include <QtCore/qt_windows.h> +typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); +static PProcessIdToSessionId pProcessIdToSessionId = 0; +#endif + +#if defined(Q_OS_UNIX) +#include <time.h> +#include <unistd.h> +#endif + +namespace SharedTools { + +const char *QtLocalPeer::ack = "ack"; + +QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) + : QObject(parent), id(appId) +{ + if (id.isEmpty()) + id = QCoreApplication::applicationFilePath(); //### On win, check if this returns .../argv[0] without casefolding; .\MYAPP == .\myapp on Win + + QByteArray idc = id.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + //### could do: two 16bit checksums over separate halves of id, for a 32bit result - improved uniqeness probability. Every-other-char split would be best. + + socketName = QLatin1String("qtsingleapplication-") + + QString::number(idNum, 16); +#if defined(Q_OS_WIN) + if (!pProcessIdToSessionId) { + QLibrary lib("kernel32"); + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } + if (pProcessIdToSessionId) { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + socketName += QLatin1Char('-') + QString::number(sessionId, 16); + } +#else + socketName += QLatin1Char('-') + QString::number(::getuid(), 16); +#endif + + server = new QLocalServer(this); + QString lockName = QDir(QDir::tempPath()).absolutePath() + + QLatin1Char('/') + socketName + + QLatin1String("-lockfile"); + lockFile.setFileName(lockName); + lockFile.open(QIODevice::ReadWrite); +} + +bool QtLocalPeer::isClient() +{ + if (lockFile.isLocked()) + return false; + + if (!lockFile.lock(QtLockedFile::WriteLock, false)) + return true; + + if (!QLocalServer::removeServer(socketName)) + qWarning("QtSingleCoreApplication: could not cleanup socket"); + bool res = server->listen(socketName); + if (!res) + qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); + return false; +} + +bool QtLocalPeer::sendMessage(const QString &message, int timeout) +{ + if (!isClient()) + return false; + + QLocalSocket socket; + bool connOk = false; + for (int i = 0; i < 2; i++) { + // Try twice, in case the other instance is just starting up + socket.connectToServer(socketName); + connOk = socket.waitForConnected(timeout/2); + if (connOk || i) + break; + int ms = 250; +#if defined(Q_OS_WIN) + Sleep(DWORD(ms)); +#else + struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; + nanosleep(&ts, NULL); +#endif + } + if (!connOk) + return false; + + QByteArray uMsg(message.toUtf8()); + QDataStream ds(&socket); + ds.writeBytes(uMsg.constData(), uMsg.size()); + bool res = socket.waitForBytesWritten(timeout); + res &= socket.waitForReadyRead(timeout); // wait for ack + res &= (socket.read(qstrlen(ack)) == ack); + return res; +} + +void QtLocalPeer::receiveConnection() +{ + QLocalSocket* socket = server->nextPendingConnection(); + if (!socket) + return; + + // Why doesn't Qt have a blocking stream that takes care of this shait??? + while (socket->bytesAvailable() < static_cast<int>(sizeof(quint32))) + socket->waitForReadyRead(); + QDataStream ds(socket); + QByteArray uMsg; + quint32 remaining; + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); + //qDebug() << "RCV: remaining" << remaining; + do { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + //qDebug() << "RCV: got" << got << "remaining" << remaining; + } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + //### error check: got<0 + if (got < 0) { + qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString(); + delete socket; + return; + } + // ### async this + QString message = QString::fromUtf8(uMsg.constData(), uMsg.size()); + socket->write(ack, qstrlen(ack)); + socket->waitForBytesWritten(1000); + delete socket; + emit messageReceived(message); // ##(might take a long time to return) +} + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtlocalpeer.h b/src/shared/qtsingleapplication/qtlocalpeer.h new file mode 100644 index 0000000..c708b9b --- /dev/null +++ b/src/shared/qtsingleapplication/qtlocalpeer.h @@ -0,0 +1,65 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtlockedfile.h" + +#include <QtNetwork/QLocalServer> +#include <QtNetwork/QLocalSocket> +#include <QtCore/QDir> + +namespace SharedTools { + +class QtLocalPeer : public QObject +{ + Q_OBJECT + +public: + QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); + bool isClient(); + bool sendMessage(const QString &message, int timeout); + QString applicationId() const + { return id; } + +Q_SIGNALS: + void messageReceived(const QString &message); + +protected Q_SLOTS: + void receiveConnection(); + +protected: + QString id; + QString socketName; + QLocalServer* server; + QtLockedFile lockFile; + +private: + static const char* ack; +}; + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsingleapplication.cpp b/src/shared/qtsingleapplication/qtsingleapplication.cpp new file mode 100644 index 0000000..2032471 --- /dev/null +++ b/src/shared/qtsingleapplication/qtsingleapplication.cpp @@ -0,0 +1,141 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtsingleapplication.h" +#include "qtlocalpeer.h" + +#include <QtGui/QWidget> +#include <QtGui/QFileOpenEvent> + +namespace SharedTools { + +void QtSingleApplication::sysInit(const QString &appId) +{ + actWin = 0; + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) + : QApplication(argc, argv, GUIenabled) +{ + sysInit(); +} + + +QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) + : QApplication(argc, argv) +{ + sysInit(appId); +} + + +QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) + : QApplication(argc, argv, type) +{ + sysInit(); +} + + +#if defined(Q_WS_X11) +QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE colormap) + : QApplication(dpy, visual, colormap) +{ + sysInit(); +} + +QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(); +} + +QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, + int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap) + : QApplication(dpy, argc, argv, visual, colormap) +{ + sysInit(appId); +} +#endif + +bool QtSingleApplication::event(QEvent *event) +{ + if (event->type() == QEvent::FileOpen) { + QFileOpenEvent *foe = static_cast<QFileOpenEvent*>(event); + emit fileOpenRequest(foe->file()); + return true; + } + return QApplication::event(event); +} + +bool QtSingleApplication::isRunning() +{ + return peer->isClient(); +} + + +bool QtSingleApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +QString QtSingleApplication::id() const +{ + return peer->applicationId(); +} + + +void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessage) +{ + actWin = aw; + if (activateOnMessage) + connect(peer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); + else + disconnect(peer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); +} + + +QWidget* QtSingleApplication::activationWindow() const +{ + return actWin; +} + + +void QtSingleApplication::activateWindow() +{ + if (actWin) { + actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); + actWin->raise(); + actWin->activateWindow(); + } +} + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsingleapplication.h b/src/shared/qtsingleapplication/qtsingleapplication.h new file mode 100644 index 0000000..0fbd77b --- /dev/null +++ b/src/shared/qtsingleapplication/qtsingleapplication.h @@ -0,0 +1,81 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QtGui/QApplication> + +namespace SharedTools { + +class QtLocalPeer; + +class QtSingleApplication : public QApplication +{ + Q_OBJECT + +public: + QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); + QtSingleApplication(const QString &id, int &argc, char **argv); + QtSingleApplication(int &argc, char **argv, Type type); +#if defined(Q_WS_X11) + QtSingleApplication(Display *dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); + QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0); +#endif + + bool isRunning(); + QString id() const; + + void setActivationWindow(QWidget* aw, bool activateOnMessage = true); + QWidget* activationWindow() const; + bool event(QEvent *event); + + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + void activateWindow(); + +//Obsolete methods: +public: + void initialize(bool = true) + { isRunning(); } + +#if defined(Q_WS_X11) + QtSingleApplication(Display* dpy, const QString &id, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); +#endif +// end obsolete methods + +Q_SIGNALS: + void messageReceived(const QString &message); + void fileOpenRequest(const QString &file); + +private: + void sysInit(const QString &appId = QString()); + QtLocalPeer *peer; + QWidget *actWin; +}; + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsingleapplication.pri b/src/shared/qtsingleapplication/qtsingleapplication.pri new file mode 100644 index 0000000..f6d8462 --- /dev/null +++ b/src/shared/qtsingleapplication/qtsingleapplication.pri @@ -0,0 +1,14 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h +SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp + +QT *= network + +gotqtlockedfile = $$find(HEADERS, .*qtlockedfile.h) +isEmpty(gotqtlockedfile):include(../qtlockedfile/qtlockedfile.pri) + + +win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + DEFINES += QT_QTSINGLEAPPLICATION_EXPORT=__declspec(dllexport) +} diff --git a/src/shared/qtsingleapplication/qtsinglecoreapplication.cpp b/src/shared/qtsingleapplication/qtsinglecoreapplication.cpp new file mode 100644 index 0000000..5cbb606 --- /dev/null +++ b/src/shared/qtsingleapplication/qtsinglecoreapplication.cpp @@ -0,0 +1,68 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qtsinglecoreapplication.h" +#include "qtlocalpeer.h" + +namespace SharedTools { + +QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + peer = new QtLocalPeer(this); + connect(peer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString))); +} + + +QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString))); +} + + +bool QtSingleCoreApplication::isRunning() +{ + return peer->isClient(); +} + + +bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +QString QtSingleCoreApplication::id() const +{ + return peer->applicationId(); +} + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsinglecoreapplication.h b/src/shared/qtsingleapplication/qtsinglecoreapplication.h new file mode 100644 index 0000000..275c520 --- /dev/null +++ b/src/shared/qtsingleapplication/qtsinglecoreapplication.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QtCore/QCoreApplication> + +namespace SharedTools { + +class QtLocalPeer; + +class QtSingleCoreApplication : public QCoreApplication +{ + Q_OBJECT + +public: + QtSingleCoreApplication(int &argc, char **argv); + QtSingleCoreApplication(const QString &id, int &argc, char **argv); + + bool isRunning(); + QString id() const; + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + + +Q_SIGNALS: + void messageReceived(const QString &message); + + +private: + QtLocalPeer* peer; +}; + +} // namespace SharedTools diff --git a/src/shared/qtsingleapplication/qtsinglecoreapplication.pri b/src/shared/qtsingleapplication/qtsinglecoreapplication.pri new file mode 100644 index 0000000..3d6301b --- /dev/null +++ b/src/shared/qtsingleapplication/qtsinglecoreapplication.pri @@ -0,0 +1,14 @@ +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h +SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp + +QT *= network + +gotqtlockedfile = $$find(HEADERS, .*qtlockedfile.h) +isEmpty(gotqtlockedfile):include(../qtlockedfile/qtlockedfile.pri) + + +win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { + DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) +} diff --git a/src/src.pri b/src/src.pri new file mode 100644 index 0000000..9513e96 --- /dev/null +++ b/src/src.pri @@ -0,0 +1,77 @@ +include(other/other.pri) +include(mobility/mobility.pri) +include(ui/ui.pri) +include(shared/qtlockedfile/qtlockedfile.pri) +include(shared/qtsingleapplication/qtsingleapplication.pri) + +DEFINES += SIMULATOR_APPLICATION + +# Input +SOURCES += src/main.cpp +HEADERS += + +# Shared communication implementation +SOURCES += $$QT_NOKIA_SDK_PATH/src/gui/kernel/qsimulatordata.cpp +HEADERS += $$QT_NOKIA_SDK_PATH/src/gui/kernel/qsimulatordata_p.h +OTHER_FILES += \ + $$QT_NOKIA_SDK_PATH/src/gui/kernel/qsimulatorconnection.cpp \ + $$QT_NOKIA_SDK_PATH/src/gui/kernel/qsimulatorconnection_p.h + +# Mobility +INCLUDEPATH += \ + $$QT_MOBILITY_SOURCE_PATH/src \ + $$QT_MOBILITY_SOURCE_PATH/src/global \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/engines \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/filters \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/details \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/requests \ + $$QT_MOBILITY_SOURCE_PATH/plugins/sensors/simulator + +SOURCES += $$QT_MOBILITY_SOURCE_PATH/src/systeminfo/qsysteminfodata_simulator.cpp \ + $$QT_MOBILITY_SOURCE_PATH/src/location/qgeopositioninfodata_simulator.cpp \ + $$QT_MOBILITY_SOURCE_PATH/src/systeminfo/qsysteminfo_simulator.cpp \ + $$QT_MOBILITY_SOURCE_PATH/src/systeminfo/qsysteminfo.cpp \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/engines/qcontactmemorybackenddata_simulator.cpp \ + $$QT_MOBILITY_SOURCE_PATH/plugins/sensors/simulator/qsensordata_simulator.cpp +HEADERS += $$QT_MOBILITY_SOURCE_PATH/src/systeminfo/qsysteminfodata_simulator_p.h \ + $$QT_MOBILITY_SOURCE_PATH/src/location/qgeopositioninfodata_simulator_p.h \ + $$QT_MOBILITY_SOURCE_PATH/src/systeminfo/qsysteminfo_simulator_p.h \ + $$QT_MOBILITY_SOURCE_PATH/src/systeminfo/qsysteminfo.h \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/engines/qcontactmemorybackenddata_simulator_p.h \ + $$QT_MOBILITY_SOURCE_PATH/plugins/sensors/simulator/qsensordata_simulator_p.h + +OTHER_FILES += \ + $$QT_MOBILITY_SOURCE_PATH/src/mobilitysimulator/mobilityconnection.cpp \ + $$QT_MOBILITY_SOURCE_PATH/src/mobilitysimulator/mobilityconnection_p.h \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/engines/qcontactsimulatorbackend_p.h \ + $$QT_MOBILITY_SOURCE_PATH/src/contacts/engines/qcontactsimulatorbackend.cpp + + +INCLUDEPATH *= $$SIMULATOR_DEPENDENCY_PATH/include +!mac { + LIBS *= -L$$SIMULATOR_DEPENDENCY_PATH/lib +} else { + QMAKE_LFLAGS *= -F$$SIMULATOR_DEPENDENCY_PATH/lib +} +unix: isEmpty(INSTALLER) { + LIBS *= -Wl,-rpath,$$SIMULATOR_DEPENDENCY_PATH/lib +} + +# link dependencies +INCLUDEPATH *= $$QMF_INCLUDEDIR $$QMF_INCLUDEDIR/support +!mac { + qtAddLibrary(qtopiamail) + qtAddLibrary(remotecontrolwidget) +} else { + LIBS += -framework qtopiamail + LIBS += -framework remotecontrolwidget +} + + +# Set rpath for shipping binaries +!mac:unix:!isEmpty(INSTALLER) { + QMAKE_RPATHDIR = \$\$ORIGIN/lib + LIBS += -Wl,-z,origin \'-Wl,-rpath,$${QMAKE_RPATHDIR}\' + QMAKE_RPATHDIR = +} diff --git a/src/ui/applicationtablewidget.cpp b/src/ui/applicationtablewidget.cpp new file mode 100644 index 0000000..b3ebb42 --- /dev/null +++ b/src/ui/applicationtablewidget.cpp @@ -0,0 +1,57 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "applicationtablewidget.h" + +#include <QtGui/QKeyEvent> + +ApplicationTableWidget::ApplicationTableWidget(QWidget *parent) + : QTableWidget(0, 2, parent) +{ + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); + + QStringList headerItems; + headerItems << "ID" << "Application Name"; + setHorizontalHeaderLabels(headerItems); +} + +ApplicationTableWidget::~ApplicationTableWidget() +{ + +} + +void ApplicationTableWidget::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Delete && currentRow() >= 0) { + QTableWidgetItem *currentItem = item(currentRow(), 0); + int applicationId = currentItem->data(0).toInt(); + emit killApplication(applicationId); + } +} diff --git a/src/ui/applicationtablewidget.h b/src/ui/applicationtablewidget.h new file mode 100644 index 0000000..1953b42 --- /dev/null +++ b/src/ui/applicationtablewidget.h @@ -0,0 +1,52 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef APPLICATIONTABLEWIDGET_H +#define APPLICATIONTABLEWIDGET_H + +#include <QtGui/QTableWidget> + +class ApplicationTableWidget : public QTableWidget +{ + Q_OBJECT + +public: + ApplicationTableWidget(QWidget *parent = 0); + ~ApplicationTableWidget(); + +private: + +protected: + virtual void keyPressEvent(QKeyEvent *e); + +signals: + void killApplication(int id); +}; + +#endif // APPLICATIONTABLEWIDGET_H diff --git a/src/ui/configurationwidget.cpp b/src/ui/configurationwidget.cpp new file mode 100644 index 0000000..8bc63e1 --- /dev/null +++ b/src/ui/configurationwidget.cpp @@ -0,0 +1,405 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "configurationwidget.h" +#include "ui_inspector.h" +#include "configurationreader.h" +#include "qsimulatordata_p.h" +#include "viewconfiguration.h" +#include "widget.h" +#include "application.h" + +#include <qmath.h> +#include <QtCore/QSettings> +#include <QtCore/QThread> +#include <QtCore/QDir> +#include <QtGui/QDesktopWidget> +#include <QtGui/QScrollBar> +#include <QtGui/QMessageBox> +#include <QtGui/QToolButton> +#include <QtGui/QCloseEvent> +#include <QtGui/QMenuBar> +#include <QtGui/QPushButton> + +ConfigurationWidget::ConfigurationWidget(QWidget *parent) + : RemoteControlWidget(parent) + , ui_inspector(new Ui_Inspector) + , mCorrectionFactor(1) + , mViewConfiguration(0) +{ + QDesktopWidget *desktop = QApplication::desktop(); + mLogicalDpi.setWidth(desktop->logicalDpiX()); + mLogicalDpi.setHeight(desktop->logicalDpiY()); + + setWindowTitle(tr("Qt Simulator")); + + mScriptInterface = new SimulatorScriptInterface(this); + + initializeApplicationArea(); + initializeViewArea(); +} + +ConfigurationWidget::~ConfigurationWidget() +{ +} + +void ConfigurationWidget::initializeViewArea() +{ + QWidget *target = new QWidget(); + ui_inspector->setupUi(target); + connect(ui_inspector->rotateButton, SIGNAL(clicked()), this, SLOT(rotate())); + connect(ui_inspector->scaleSlider, SIGNAL(valueChanged(int)), this, SLOT(changeScaleFactor(int))); + connect(ui_inspector->deviceListView, SIGNAL(currentIndexChanged(int)), this, SLOT(changeDeviceSelection(int))); + + mViewPage = new PageWidget(tr("View"), target); + mViewPage->setHideable(true); + mViewPage->setHasAdvancedButton(true); + connect(mViewPage, SIGNAL(advancedButtonClicked()), SLOT(showViewConfiguration())); + addPage(mViewPage); +} + +void ConfigurationWidget::initializeApplicationArea() +{ + QWidget *target = new QWidget(); + QFormLayout *innerLayout = new QFormLayout(); + mWidgetTitle = new QLineEdit(); + mWidgetTitle->setReadOnly(true); + innerLayout->addRow(tr("Topmost widget's title"), mWidgetTitle); + mMenuLayout = new QHBoxLayout(); + innerLayout->addRow(tr("Application's menubar"), mMenuLayout); + QPushButton *exitButton = new QPushButton(tr("Quit")); + connect(exitButton, SIGNAL(clicked()), SIGNAL(exitButtonClicked())); + innerLayout->addRow(tr("Quit current application"), exitButton); + target->setLayout(innerLayout); + + mAppPage = new PageWidget(tr("Application"), target); + mAppPage->setHideable(true); + mAppPage->hideContent(); + addPage(mAppPage); +} + +int ConfigurationWidget::currentDeviceIndex() const +{ + return ui_inspector->deviceListView->currentIndex(); +} + +QString ConfigurationWidget::currentDeviceName() const +{ + return ui_inspector->deviceListView->currentText(); +} + +void ConfigurationWidget::changeDeviceSelection(int newIndex) +{ + ui_inspector->deviceListView->setCurrentIndex(newIndex); + const DeviceData &newData = deviceList.at(newIndex); + emit deviceSelectionChanged(newData); + changeScaleFactor(ui_inspector->scaleSlider->value()); +} + +void ConfigurationWidget::updateTopWidget(Widget *topWidget) +{ + QMenuBar *menuBar = 0; + if (topWidget) { + menuBar = topWidget->menuBar(); + mWidgetTitle->setText(topWidget->title); + } else { + mWidgetTitle->setText(QString()); + } + + if (mMenuBar == menuBar) + return; + + if (mMenuBar) { + mMenuBar->hide(); + mMenuLayout->removeWidget(mMenuBar); + } + + mMenuBar = menuBar; + if (!menuBar) + return; + + mMenuLayout->insertWidget(0, mMenuBar); + mMenuBar->show(); +} + +void ConfigurationWidget::initializeSelection() +{ + if (deviceList.count() == 0) + return; + + ui_inspector->deviceListView->setCurrentIndex(0); + changeDeviceSelection(0); +} + +void ConfigurationWidget::changeScaleFactor(int sliderPosition) +{ + int index = currentDeviceIndex(); + if (index < 0 || index >= deviceList.size()) + return; + + const DeviceData &data = deviceList.at(index); + qreal pixelDiagonal = sqrt(pow((qreal)data.resolution.width(), 2) + pow((qreal)data.resolution.height(), 2)); + qreal displayWidthInInch = data.diagonalInInch / pixelDiagonal * data.resolution.width(); + + qreal minimalScale = mLogicalDpi.width() * displayWidthInInch / data.resolution.width() * mCorrectionFactor; + + emit scaleFactorChanged((minimalScale + qreal(sliderPosition) / 100. * (1. - minimalScale))); +} + +void ConfigurationWidget::changeCorrectionFactor(qreal newFactor) +{ + mCorrectionFactor = newFactor; + changeScaleFactor(ui_inspector->scaleSlider->value()); +} + +void ConfigurationWidget::closeEvent(QCloseEvent *event) +{ + event->ignore(); + emit closeMainWindow(); +} + +void ConfigurationWidget::rotate() +{ + emit rotateRequested(); +} + +void ConfigurationWidget::writeSettings(const QString &vendor, const QString &name) const +{ + RemoteControlWidget::writeSettings(vendor, name); + + QSettings settings(vendor, name); + + settings.beginGroup("ConfigurationWidget"); + settings.setValue("scale", ui_inspector->scaleSlider->value()); + settings.setValue("corrfactor", mCorrectionFactor); + settings.setValue("viewPageVisible", mViewPage->isContentVisible()); + settings.setValue("appPageVisible", mAppPage->isContentVisible()); + + int index = currentDeviceIndex(); + if (index >= 0 && index < deviceList.size()) + settings.setValue("device", deviceList.at(index).name); + + settings.endGroup(); +} + +void ConfigurationWidget::readSettings(const QString &vendor, const QString &name) +{ + RemoteControlWidget::readSettings(vendor, name); + + QSettings settings(vendor, name); + + settings.beginGroup("ConfigurationWidget"); + if (settings.contains("scale")) + ui_inspector->scaleSlider->setValue(settings.value("scale").toInt()); + if (settings.contains("corrfactor")) { + changeCorrectionFactor(settings.value("corrfactor").toDouble()); + } + if (settings.contains("viewPageVisible")) { + bool viewPageVisible = settings.value("viewPageVisible").toBool(); + if (viewPageVisible) + mViewPage->showContent(); + else + mViewPage->hideContent(); + } + if (settings.contains("appPageVisible")) { + bool appPageVisible = settings.value("appPageVisible").toBool(); + if (appPageVisible) + mAppPage->showContent(); + else + mAppPage->hideContent(); + } + + if (settings.contains("device")) { + QString deviceName = settings.value("device").toString(); + for (int i = 0; i < deviceList.size(); ++i) { + if (deviceList.at(i).name == deviceName) + ui_inspector->deviceListView->setCurrentIndex(i); + } + } + + settings.endGroup(); +} + +void ConfigurationWidget::showViewConfiguration() +{ + if (!mViewConfiguration) { + mViewConfiguration = new ViewConfiguration(mCorrectionFactor, this); + connect(mViewConfiguration, SIGNAL(correctionFactorChanged(qreal)), SLOT(changeCorrectionFactor(qreal))); + } + + mViewConfiguration->exec(); + +} + +bool ConfigurationWidget::initializeDeviceList() +{ + QDir modelsDir("models"); + if (!modelsDir.exists()) { + QMessageBox errorMsg; + errorMsg.setWindowTitle(tr("Folder does not exist")); + errorMsg.setText(tr("The \"%1\" folder could not be located in the installation directory.").arg(modelsDir.dirName())); + errorMsg.setIcon(QMessageBox::Critical); + errorMsg.exec(); + return false; + } + + ConfigurationReader confReader; + deviceList.clear(); + bool noErrors = confReader.processDir(&modelsDir, deviceList); + if (!noErrors && !deviceList.isEmpty()) { + QMessageBox msgbox; + msgbox.setWindowTitle(tr("Errors occurred while reading device configurations")); + msgbox.setText(confReader.errorMessageLines()); + msgbox.setIcon(QMessageBox::Critical); + msgbox.exec(); + } + + if (deviceList.isEmpty()) { + QMessageBox errorMsg; + errorMsg.setWindowTitle(tr("Devices could not be found")); + QString msg; + if (!noErrors) { + msg = confReader.errorMessageLines(); + } + msg += tr("No valid device configuration files (.config) could be found in the \"%1\" folder.").arg(modelsDir.dirName()); + errorMsg.setText(msg); + errorMsg.setIcon(QMessageBox::Critical); + errorMsg.exec(); + return false; + } + + foreach (const DeviceData &data, deviceList) + ui_inspector->deviceListView->addItem(data.name); + return true; +} + +SimulatorScriptInterface *ConfigurationWidget::scriptInterface() +{ + return mScriptInterface; +} + +SimulatorScriptInterface::SimulatorScriptInterface(ConfigurationWidget *ui) + : QObject(ui), ui(ui) +{ +} + +SimulatorScriptInterface::~SimulatorScriptInterface() +{ +} + +/*! + \class SimulatorScriptInterface + \brief Exposed as simulator. +*/ + +/*! + \property SimulatorScriptInterface::zoom + + \brief the device scaling + + The value can be between between 0 for real-world size and 100 for pixel equivalence. + +*/ +int SimulatorScriptInterface::zoom() const +{ + return ui->ui_inspector->scaleSlider->value(); +} + +void SimulatorScriptInterface::setZoom(int z) +{ + if (z < 0) + z = 0; + else if (z > 100) + z = 100; + ui->ui_inspector->scaleSlider->setValue(z); +} + +/*! + Returns the index of the current device. + + \sa setDevice(), deviceCount() +*/ +int SimulatorScriptInterface::currentDeviceIndex() const +{ + return ui->currentDeviceIndex(); +} + +/*! + Returns the name of the current device. + + \sa setDevice() +*/ +QString SimulatorScriptInterface::currentDeviceName() const +{ + return ui->currentDeviceName(); +} + +/*! + Returns the number of available device models. + + \sa setDevice(), currentDeviceIndex() +*/ +int SimulatorScriptInterface::deviceCount() const +{ + return ui->deviceList.size(); +} + +/*! + Rotates the current device. +*/ +void SimulatorScriptInterface::rotate() +{ + ui->rotate(); +} + +/*! + Sets the current device to the one with \a index. + + \sa deviceCount(), currentDeviceIndex() +*/ +void SimulatorScriptInterface::setDevice(int index) +{ + ui->changeDeviceSelection(index); +} + +/*! + Sets the current device to be the one identified by \a dev. + + \sa currentDeviceName() +*/ +void SimulatorScriptInterface::setDevice(const QString &dev) +{ + const QList<DeviceData> &devices = ui->deviceList; + for (int i = 0; i < devices.size(); ++i) { + if (devices.at(i).name == dev) { + ui->changeDeviceSelection(i); + break; + } + } +} diff --git a/src/ui/configurationwidget.h b/src/ui/configurationwidget.h new file mode 100644 index 0000000..8f9f63e --- /dev/null +++ b/src/ui/configurationwidget.h @@ -0,0 +1,141 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CONFIGURATIONWIDGET_H +#define CONFIGURATIONWIDGET_H + +#include "deviceitem.h" + +#include <remotecontrolwidget/remotecontrolwidget.h> + +#include <QtGui/QWidget> +#include <QtCore/QPointer> + +class Ui_Inspector; +class OptionsItem; +class FilterLineEdit; +class MobilityData; +class ToolBox; +class ToolBoxPage; +class StyledBar; +class QToolButton; +class QMenuBar; +class ViewConfiguration; +class QLineEdit; +class Widget; +class SimulatorScriptInterface; + +class ConfigurationWidget: public RemoteControlWidget +{ + Q_OBJECT +public: + explicit ConfigurationWidget(QWidget *parent = 0); + ~ConfigurationWidget(); + + SimulatorScriptInterface *scriptInterface(); + + void initializeSelection(); + + int currentDeviceIndex() const; + QString currentDeviceName() const; + + bool initializeDeviceList(); + + virtual void writeSettings(const QString &vendor, const QString &name) const; + virtual void readSettings(const QString &vendor, const QString &name); + +public slots: + void changeDeviceSelection(int newIndex); + void updateTopWidget(Widget *topWidget); + +signals: + void deviceSelectionChanged(const DeviceData &data); + void scaleFactorChanged(qreal newScaleFactor); + void rotateRequested(); + void closeMainWindow(); + void exitButtonClicked(); + +protected: + virtual void closeEvent(QCloseEvent *event); + +private slots: + void changeScaleFactor(int sliderPosition); + void changeCorrectionFactor(qreal); + void rotate(); + void showViewConfiguration(); + +private: + void initializeViewArea(); + void initializeApplicationArea(); + + QList<DeviceData> deviceList; + Ui_Inspector *ui_inspector; + qreal mCorrectionFactor; + + QSize mLogicalDpi; + + QToolButton *viewButton; + + ViewConfiguration *mViewConfiguration; + QHBoxLayout *mMenuLayout; + QLineEdit *mWidgetTitle; + + PageWidget *mAppPage; + PageWidget *mViewPage; + + QPointer<QMenuBar> mMenuBar; + + SimulatorScriptInterface *mScriptInterface; + friend class SimulatorScriptInterface; +}; + +class SimulatorScriptInterface : public QObject +{ + Q_OBJECT +public: + SimulatorScriptInterface(ConfigurationWidget *ui); + virtual ~SimulatorScriptInterface(); + + Q_PROPERTY(int zoom READ zoom WRITE setZoom) + + int zoom() const; + void setZoom(int z); + + Q_INVOKABLE int currentDeviceIndex() const; + Q_INVOKABLE QString currentDeviceName() const; + Q_INVOKABLE int deviceCount() const; + Q_INVOKABLE void rotate(); + Q_INVOKABLE void setDevice(const QString & dev); + Q_INVOKABLE void setDevice(int index); + +private: + ConfigurationWidget *ui; +}; + +#endif //CONFIGURATIONWIDGET_H diff --git a/src/ui/contactsui.cpp b/src/ui/contactsui.cpp new file mode 100644 index 0000000..e111dbc --- /dev/null +++ b/src/ui/contactsui.cpp @@ -0,0 +1,103 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "contactsui.h" + +#include "contacts.h" +#include "configurationwidget.h" + +#include <remotecontrolwidget/optionsitem.h> + +#include <contacts/qcontactmanager.h> +#include <contacts/qcontact.h> +#include <contacts/details/qcontactname.h> + +#include <QtCore/QList> +#include <QtGui/QPushButton> +#include <QtGui/QTableWidget> +#include <QtGui/QFileDialog> +#include <QtGui/QMessageBox> + +ContactsUi::ContactsUi(Contacts *contacts, QWidget *parent) + : ToolBoxPage(parent) + , mContacts(contacts) + , mContactList(0) +{ + QStringList tags; + QList<OptionsItem *> optionsList; + + mContactList = new QTableWidget(); + mContactList->setColumnCount(1); + mContactList->setColumnWidth(0, mContactList->width() - mContactList->frameWidth()); + mContactList->setHorizontalHeaderLabels(QStringList(tr("Name"))); + mContactList->horizontalHeaderItem(0)->setTextAlignment(Qt::AlignLeft); + OptionsItem *item = new OptionsItem("", mContactList, true); + item->setTags(tags); + optionsList << item; + + QPushButton *contactsImportButton = new QPushButton(tr("Import")); + connect(contactsImportButton, SIGNAL(clicked()), this, SLOT(importContacts())); + item = new OptionsItem("", contactsImportButton, true); + item->setTags(tags); + optionsList << item; + + connect(mContacts, SIGNAL(contactsAdded(QList<QContactLocalId>)), this, SLOT(updateContactList())); + connect(mContacts, SIGNAL(contactsRemoved(QList<QContactLocalId>)), this, SLOT(updateContactList())); + connect(mContacts, SIGNAL(contactsChanged(QList<QContactLocalId>)), this, SLOT(updateContactList())); + connect(mContacts, SIGNAL(contactsDataChanged(const QContactManager &)), this, SLOT(updateContactList())); + + setTitle(tr("Contacts")); + setOptions(optionsList); +} + +void ContactsUi::importContacts() +{ + QString importFile = QFileDialog::getOpenFileName(0, tr("Select vCard File to Import"), ".", "*.vcf"); + if (importFile.isNull()) + return; + + if (!mContacts->importFromVCardFile(importFile)) { + QMessageBox::information(0, tr("Import Failed"), + tr("Sorry, unable to import \"%1\".").arg(importFile)); + } + + updateContactList(); +} + +void ContactsUi::updateContactList() { + QList<QContactLocalId> contactIds = mContacts->manager()->contactIds(); + mContactList->setRowCount(contactIds.size()); + + int row = 0; + foreach (const QContactLocalId &id, contactIds) { + QString name = mContacts->manager()->contact(id).displayLabel(); + mContactList->setItem(row++, 0, new QTableWidgetItem(name)); + } +} + diff --git a/src/ui/contactsui.h b/src/ui/contactsui.h new file mode 100644 index 0000000..6d756dc --- /dev/null +++ b/src/ui/contactsui.h @@ -0,0 +1,56 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CONTACTSUI_H +#define CONTACTSUI_H + +#include <remotecontrolwidget/toolbox.h> + +#include <QtCore/QObject> + +class ConfigurationWidget; +class Contacts; +class QTableWidget; + +class ContactsUi : public ToolBoxPage +{ + Q_OBJECT +public: + explicit ContactsUi(Contacts *contacts, QWidget *parent = 0); + +private slots: + void importContacts(); + void updateContactList(); + +private: + Contacts *mContacts; + QTableWidget *mContactList; +}; + +#endif // CONTACTSUI_H diff --git a/src/ui/icons/hicolor/128x128/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/128x128/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..3530343 --- /dev/null +++ b/src/ui/icons/hicolor/128x128/apps/Nokia-Simulator.png diff --git a/src/ui/icons/hicolor/16x16/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/16x16/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..6734273 --- /dev/null +++ b/src/ui/icons/hicolor/16x16/apps/Nokia-Simulator.png diff --git a/src/ui/icons/hicolor/24x24/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/24x24/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..c22d6fc --- /dev/null +++ b/src/ui/icons/hicolor/24x24/apps/Nokia-Simulator.png diff --git a/src/ui/icons/hicolor/256x256/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/256x256/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..e3c6843 --- /dev/null +++ b/src/ui/icons/hicolor/256x256/apps/Nokia-Simulator.png diff --git a/src/ui/icons/hicolor/32x32/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/32x32/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..3f41ef8 --- /dev/null +++ b/src/ui/icons/hicolor/32x32/apps/Nokia-Simulator.png diff --git a/src/ui/icons/hicolor/48x48/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/48x48/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..7aa7dfe --- /dev/null +++ b/src/ui/icons/hicolor/48x48/apps/Nokia-Simulator.png diff --git a/src/ui/icons/hicolor/64x64/apps/Nokia-Simulator.png b/src/ui/icons/hicolor/64x64/apps/Nokia-Simulator.png Binary files differnew file mode 100644 index 0000000..c4efee1 --- /dev/null +++ b/src/ui/icons/hicolor/64x64/apps/Nokia-Simulator.png diff --git a/src/ui/inspector.ui b/src/ui/inspector.ui new file mode 100644 index 0000000..2aacfe8 --- /dev/null +++ b/src/ui/inspector.ui @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Inspector</class> + <widget class="QWidget" name="Inspector"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>388</width> + <height>126</height> + </rect> + </property> + <property name="windowTitle"> + <string>Device Control</string> + </property> + <property name="styleSheet"> + <string/> + </property> + <layout class="QVBoxLayout" name="mainLayout"> + <property name="spacing"> + <number>0</number> + </property> + <property name="margin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="viewFrame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>250</height> + </size> + </property> + <layout class="QFormLayout" name="viewLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Device</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="deviceListView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="rotateButton"> + <property name="text"> + <string>Rotate Device</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Zoom</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QSlider" name="scaleSlider"> + <property name="minimum"> + <number>0</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <item> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Native size</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Native resolution</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item row="3" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_3"/> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/ui/locationui.cpp b/src/ui/locationui.cpp new file mode 100644 index 0000000..53e8e03 --- /dev/null +++ b/src/ui/locationui.cpp @@ -0,0 +1,117 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "locationui.h" + +#include "optionsitem.h" +#include "configurationwidget.h" +#include "location.h" + +#include <location/qgeopositioninfodata_simulator_p.h> + +#include <QtGui/QLineEdit> +#include <QtGui/QDoubleValidator> +#include <QtGui/QPushButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QDateTimeEdit> + +LocationUi::LocationUi(ConfigurationWidget *w, Location *location) + : QObject(w) + , mLocation(location) + , mLatitudeEdit(0) + , mLongitudeEdit(0) + , mAltitudeEdit(0) + , mTimeEdit(0) +{ + QStringList tags; + QList<OptionsItem *> optionsList; + + mLatitudeEdit = new QLineEdit("52.5056819"); + mLatitudeEdit->setValidator(new QDoubleValidator(-90, 90, 10, this)); + OptionsItem *item = new OptionsItem(tr("Latitude"), mLatitudeEdit); + connect(mLatitudeEdit, SIGNAL(editingFinished()), SLOT(triggerLocationInfoChange())); + item->setTags(tags); + optionsList << item; + + mLongitudeEdit = new QLineEdit("13.3232027"); + mLatitudeEdit->setValidator(new QDoubleValidator(-180, 180, 10, this)); + item = new OptionsItem(tr("Longitude"), mLongitudeEdit); + connect(mLongitudeEdit, SIGNAL(editingFinished()), SLOT(triggerLocationInfoChange())); + item->setTags(tags); + optionsList << item; + + mAltitudeEdit = new QLineEdit("13.3232027"); + mAltitudeEdit->setValidator(new QDoubleValidator(-15000, 15000, 10, this)); + item = new OptionsItem(tr("Altitude"), mAltitudeEdit); + connect(mAltitudeEdit, SIGNAL(editingFinished()), SLOT(triggerLocationInfoChange())); + item->setTags(tags); + optionsList << item; + + mTimeEdit = new QDateTimeEdit(); + QPushButton *locationTimeButton = new QPushButton(tr("Now")); + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->setContentsMargins(0, 0, 0, 0); + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->addWidget(mTimeEdit); + vLayout->addWidget(locationTimeButton); + hLayout->addLayout(vLayout); + QWidget *tmp = new QWidget(); + tmp->setLayout(hLayout); + connect(mTimeEdit, SIGNAL(dateTimeChanged(const QDateTime &)), SLOT(triggerLocationInfoChange())); + connect(locationTimeButton, SIGNAL(clicked()), this, SLOT(updateLocationTime())); + item = new OptionsItem(tr("Timestamp"), tmp); + item->setTags(tags); + optionsList << item; + connect(mLocation, SIGNAL(locationChanged(QGeoPositionInfoData)), this, SLOT(locationSetData())); + + w->addToolBoxPage(tr("Location"), optionsList); +} + +void LocationUi::triggerLocationInfoChange() +{ + mLocation->setLatitude(mLatitudeEdit->text().toDouble()); + mLocation->setLongitude(mLongitudeEdit->text().toDouble()); + mLocation->setAltitude(mAltitudeEdit->text().toDouble()); + mLocation->setDateTime(mTimeEdit->dateTime()); + mLocation->publish(); +} + +void LocationUi::updateLocationTime() +{ + mTimeEdit->setDateTime(QDateTime::currentDateTime()); +} + +void LocationUi::locationSetData() +{ + mLatitudeEdit->setText(QString::number(mLocation->latitude(), 'f', 8)); + mLongitudeEdit->setText(QString::number(mLocation->longitude(), 'f', 8)); + mAltitudeEdit->setText(QString::number(mLocation->altitude(), 'f', 8)); + mTimeEdit->setDateTime(mLocation->dateTime()); +} + diff --git a/src/ui/locationui.h b/src/ui/locationui.h new file mode 100644 index 0000000..d241237 --- /dev/null +++ b/src/ui/locationui.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef LOCATIONUI_H +#define LOCATIONUI_H + +#include <QtCore/QObject> + +class ConfigurationWidget; +class Location; +class QLineEdit; +class QDateTimeEdit; + +class LocationUi : public QObject +{ + Q_OBJECT +public: + LocationUi(ConfigurationWidget* w, Location *location); + +private slots: + void updateLocationTime(); + void locationSetData(); + void triggerLocationInfoChange(); + +private: + Location *mLocation; + QLineEdit *mLatitudeEdit; + QLineEdit *mLongitudeEdit; + QLineEdit *mAltitudeEdit; + QDateTimeEdit *mTimeEdit; +}; + +#endif // LOCATIONUI_H diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp new file mode 100644 index 0000000..a62140b --- /dev/null +++ b/src/ui/mainwindow.cpp @@ -0,0 +1,399 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "mainwindow.h" +#include "configurationwidget.h" +#include "displaywidget.h" +#include "applicationmanager.h" +#include "phononmanager.h" +#include "widgetmanager.h" +#include "mobilitymanager.h" +#include "mobilitydata.h" + +#include "contactsui.h" +#include "systeminfogenericui.h" +#include "systeminfonetworkui.h" +#include "systeminfostorageui.h" +#include "messagingui.h" +#include "sensorsui.h" + +#include <remotecontrolwidget/locationui.h> +#include <remotecontrolwidget/scriptui.h> +#include <remotecontrolwidget/scriptadapter.h> +#include <remotecontrolwidget/batterybutton.h> +#include <remotecontrolwidget/powerbutton.h> +#include <remotecontrolwidget/signalstrengthbutton.h> +#include <remotecontrolwidget/networkmodebutton.h> +#include <remotecontrolwidget/favoritescriptbutton.h> + +#include <QtCore/QDebug> +#include <QtCore/QTimer> +#include <QtCore/QSettings> +#include <QtCore/QDir> +#include <QtGui/QKeyEvent> +#include <QtGui/QLayout> +#include <QtGui/QGraphicsView> +#include <QtGui/QPixmap> +#include <QtGui/QPushButton> +#include <QtGui/QApplication> +#include <QtGui/QDesktopWidget> + +#if defined(Q_WS_X11) +#include <private/qt_x11_p.h> +#include <QtGui/QX11Info> +#endif + +MainWindow::MainWindow(QWidget *parent) + : QWidget(parent) + , view(0) + , config(0) + , applicationManager(0) + , deviceItem(0) + , debugWindow(0) + , startupError(false) +{ + setWindowIcon(QIcon(":/ui/icons/hicolor/256x256/apps/Nokia-Simulator.png")); + + applicationManager = new ApplicationManager(this); + if (applicationManager->simulatorAlreadyStarted() + || !applicationManager->initializeFontDirectory()) { + QTimer::singleShot(0, this, SLOT(close())); + startupError = true; + return; + } + + MobilityData *mobility = new MobilityData(this); + mobilityServer = new MobilityServer(mobility, this); + + setWindowTitle(tr("Qt Simulator")); +#ifdef Q_OS_MAC + // Sorry, widgets with translucent background are broken on MacOS X. + // Wait until QTBUG-6831 is fixed. +#else + setAttribute(Qt::WA_TranslucentBackground); + setWindowFlags(Qt::FramelessWindowHint); + // set a mask, because kwin's compositor won't draw shadows under the window then + setMask(QRect(0,0,4096,4096)); +#endif + + scene = new QGraphicsScene(this); + + deviceItem = new DeviceItem; + + scene->addItem(deviceItem); + + view = new QGraphicsView(scene); + view->setOptimizationFlag(QGraphicsView::DontSavePainterState); + view->setRenderHint(QPainter::SmoothPixmapTransform); + view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + // otherwise the graphics view won't be transparent + view->viewport()->setAutoFillBackground(false); + + PhononManager* phononManager = new PhononManager(this); + phononManager->setObjectName("PhononManager"); + applicationManager->setPhononManager(phononManager); + + WidgetManager *widgetManager = new WidgetManager(deviceItem->display(), this); + applicationManager->setWidgetManager(widgetManager); + + connect(applicationManager, SIGNAL(applicationUnRegistered(int)), widgetManager, SLOT(onApplicationUnregistered(int))); + connect(deviceItem, SIGNAL(deviceChanged(QSize,DeviceData)), applicationManager, SLOT(updateDisplayInformation(QSize,DeviceData))); + connect(deviceItem, SIGNAL(drag(QPoint)), this, SLOT(dragFromView(QPoint))); + connect(deviceItem, SIGNAL(viewSizeRequired(QSize)), this, SLOT(setViewSize(QSize))); + connect(deviceItem, SIGNAL(buttonPressed(Qt::Key, QString)), widgetManager, SLOT(sendKeyPress(Qt::Key, QString))); + connect(deviceItem, SIGNAL(buttonReleased(Qt::Key)), widgetManager, SLOT(sendKeyRelease(Qt::Key))); + connect(deviceItem, SIGNAL(offsetChanged(const QPoint &)), widgetManager, SLOT(changeOffset(const QPoint &))); + connect(deviceItem, SIGNAL(orientationChanged(Orientation, Orientation)), mobility, SLOT(rotateDevice(Orientation, Orientation))); + connect(deviceItem, SIGNAL(deviceChanged(Orientation, Orientation, Orientation)), + mobility, SLOT(changeDevice(Orientation, Orientation, Orientation))); + + view->setFrameStyle(QFrame::NoFrame); + view->setParent(this); + + // Setup debug window. + debugWindow = new QWidget(this); + debugWindow->setWindowFlags(Qt::Window); + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(applicationManager->logWidget()); + layout->addWidget(widgetManager->logWidget()); + debugWindow->setLayout(layout); + + // Setup configuration window. + config = new ConfigurationWidget(this); + if (!config->initializeDeviceList()) { + QTimer::singleShot(0, this, SLOT(close())); + startupError = true; + return; + } + connect(widgetManager, SIGNAL(topWidgetChanged(Widget *)), config, SLOT(updateTopWidget(Widget *))); + connect(config, SIGNAL(deviceSelectionChanged(const DeviceData &)), deviceItem, SLOT(changeDevice(const DeviceData &))); + connect(deviceItem, SIGNAL(sizeChanged(const QSize &)), this, SLOT(setSizeToDevice(const QSize &))); + connect(config, SIGNAL(closeMainWindow()), this, SLOT(close())); + connect(config, SIGNAL(rotateRequested()), deviceItem, SLOT(toggleOrientation())); + connect(config, SIGNAL(scaleFactorChanged(qreal)), deviceItem, SLOT(changeScaleFactor(qreal))); + connect(config, SIGNAL(exitButtonClicked()), applicationManager, SLOT(killCurrentApplication())); + + scriptAdapter = new ScriptAdapter(this); + + // build ui pages + GenericSystemInfoUi *genericSystemInfoUi = new GenericSystemInfoUi(this); + mobility->mSystemInfoGenericUi = genericSystemInfoUi; + config->addSimulateSubPage(genericSystemInfoUi); + + StorageSystemInfoUi *storageSystemInfoUi = new StorageSystemInfoUi(this); + mobility->mSystemInfoStorageUi = storageSystemInfoUi; + config->addSimulateSubPage(storageSystemInfoUi); + + NetworkSystemInfoUi *networkSystemInfoUi = new NetworkSystemInfoUi(this); + mobility->mSystemInfoNetworkUi = networkSystemInfoUi; + config->addSimulateSubPage(networkSystemInfoUi); + + LocationUi *locationUi = new LocationUi(this); + mobility->mLocationUi = locationUi; + config->addSimulateSubPage(locationUi); + + config->addSimulateSubPage(new ContactsUi(mobility->mContacts, this)); + config->addSimulateSubPage(new MessagingUi(mobility, this)); + + SensorsUi *sensorsUi = new SensorsUi(this); + mobility->mSensorsUi = sensorsUi; + config->addSimulateSubPage(sensorsUi); + + config->addSimulateSubPage(new ScriptUi(scriptAdapter, this)); + + NetworkModeButton *networkModeButton = new NetworkModeButton(this); + connect(networkModeButton, SIGNAL(networkModeChanged(NetworkModeButton::NetworkMode)), + networkSystemInfoUi, SLOT(setCurrentNetworkMode(NetworkModeButton::NetworkMode))); + connect(networkSystemInfoUi, SIGNAL(currentNetworkModeChanged(NetworkModeButton::NetworkMode)), + networkModeButton, SLOT(setDisplayedNetworkMode(NetworkModeButton::NetworkMode))); + config->addMenuButton(networkModeButton); + + SignalStrengthButton *signalStrengthButton = new SignalStrengthButton(this); + connect(signalStrengthButton, SIGNAL(signalStrengthChanged(SignalStrengthButton::SignalStrength)), + networkSystemInfoUi, SLOT(setCurrentNetworkSignalStrength(SignalStrengthButton::SignalStrength))); + connect(networkSystemInfoUi, SIGNAL(currentNetworkSignalStrengthChanged(SignalStrengthButton::SignalStrength)), + signalStrengthButton, SLOT(setDisplayedSignalStrength(SignalStrengthButton::SignalStrength))); + config->addMenuButton(signalStrengthButton); + + BatteryButton *batteryButton = new BatteryButton(this); + connect(batteryButton, SIGNAL(batteryLevelChanged(BatteryButton::BatteryLevel)), + mobility->mSystemInfoGenericUi, SLOT(setCurrentBatteryLevel(BatteryButton::BatteryLevel))); + connect(mobility->mSystemInfoGenericUi, SIGNAL(currentBatteryLevelChanged(BatteryButton::BatteryLevel)), + batteryButton, SLOT(setDisplayedBatteryLevel(BatteryButton::BatteryLevel))); + config->addMenuButton(batteryButton); + + PowerButton *powerButton = new PowerButton(this); + connect(powerButton, SIGNAL(powerStateChanged(PowerButton::PowerState)), + mobility->mSystemInfoGenericUi, SLOT(setCurrentPowerState(PowerButton::PowerState))); + connect(mobility->mSystemInfoGenericUi, SIGNAL(currentPowerStateChanged(PowerButton::PowerState)), + powerButton, SLOT(setDisplayedState(PowerButton::PowerState))); + config->addMenuButton(powerButton); + + FavoriteScriptButton *scriptButton = new FavoriteScriptButton(this); + connect(scriptButton, SIGNAL(scriptSelected(QString)), + scriptAdapter, SLOT(run(QString))); + // ### Should be a path in the user directory, not next to the executable! + QDir scriptDir(QCoreApplication::applicationDirPath()); + scriptDir.cd("scripts"); + scriptDir.cd("favorites"); + scriptButton->setPath(scriptDir.path()); + config->addMenuButton(scriptButton); + + // register script interfaces + scriptAdapter->addScriptInterface("simulator", config->scriptInterface()); + scriptAdapter->addScriptInterface("sensors", sensorsUi->scriptInterface()); + scriptAdapter->addScriptInterface("location", locationUi->scriptInterface()); + scriptAdapter->addScriptInterface("sysinfo.generic", genericSystemInfoUi->scriptInterface()); + scriptAdapter->addScriptInterface("sysinfo.network", networkSystemInfoUi->scriptInterface()); + scriptAdapter->addScriptInterface("sysinfo.storage", storageSystemInfoUi->scriptInterface()); + + connect(config, SIGNAL(deviceSelectionChanged(const DeviceData &)), SLOT(callDeviceScript(const DeviceData &))); + + config->initializeSelection(); + config->setWindowFlags(Qt::Tool); + config->readSettings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + + mobility->setInitialData(); + + config->show(); + + // Filter to show debug window on special key press. + view->installEventFilter(this); + view->setFocus(); + + readSettings(); + scriptAdapter->runAutostartScripts(); +} + +MainWindow::~MainWindow() +{ +} + +bool MainWindow::eventFilter(QObject *watched, QEvent *event) +{ + if (watched == view) + { + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); + if (keyEvent->key() == Qt::Key_F9 + && keyEvent->modifiers() & Qt::ControlModifier) + { + debugWindow->show(); + } + } + } + return false; +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + if (applicationManager->hasApplications()) { + event->ignore(); + applicationManager->killAllApplications(); + connect(applicationManager, SIGNAL(lastAppUnregistered()), this, SLOT(close())); + return; + } + + if (!startupError) { + writeSettings(); + config->writeSettings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + } +} + +void MainWindow::setSizeToDevice(const QSize &size) +{ + QSize targetSize(size); + + // don't try to make windows bigger than allowed on X11 +#ifdef Q_WS_X11 + QSize maxSize = QApplication::desktop()->availableGeometry(this).size(); + targetSize = targetSize.boundedTo(maxSize); +#endif + setMaximumSize(targetSize); + resize(targetSize); +} + +void MainWindow::dragFromView(const QPoint &to) +{ +#ifdef Q_WS_X11 + XEvent xev; + xev.xclient.type = ClientMessage; + xev.xclient.message_type = ATOM(_NET_WM_MOVERESIZE); + xev.xclient.display = X11->display; + xev.xclient.window = winId(); + xev.xclient.format = 32; + xev.xclient.data.l[0] = to.x(); + xev.xclient.data.l[1] = to.y(); + // only moving (the "move via keyboard" value seems to impose less + // movement restrictions) + xev.xclient.data.l[2] = 10; + xev.xclient.data.l[3] = Button1; + xev.xclient.data.l[4] = 2; // user event + XUngrabPointer(X11->display, X11->time); + XSendEvent(X11->display, QX11Info::appRootWindow(x11Info().screen()), False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); +#else + move(to - view->pos()); +#endif +} + +void MainWindow::setViewSize(const QSize &size) +{ + QSize targetSize(size); + + // X11 seems to be unable to draw windows bigger than the available desktop geometry. + // Therefore, we enable scroll bars there if the view is required to be bigger than that. +#ifdef Q_WS_X11 + QSize maxSize = QApplication::desktop()->availableGeometry(this).size(); + targetSize = targetSize.boundedTo(maxSize); + // the first check is for whether we're rotating at the moment + if (targetSize == this->size() || targetSize == size) { + view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + } else { + view->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + view->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + } + + // adjust the window mask, otherwise the window is transparent, but clickable + setMask(QRect(QPoint(width() - targetSize.width(), height() - targetSize.height()) / 2, targetSize)); +#endif + + // resize and center the view + view->move(QPoint(width() - targetSize.width(), height() - targetSize.height()) / 2); + view->resize(targetSize); + + view->setSceneRect(0, 0, size.width(), size.height()); + view->centerOn(size.width() / 2, size.height() / 2); +} + +void MainWindow::writeSettings() const +{ + QSettings settings; + + settings.beginGroup("MainWindow"); + settings.setValue("pos", pos()); + settings.endGroup(); +} + +void MainWindow::readSettings() +{ + QSettings settings; + + settings.beginGroup("MainWindow"); + if (settings.contains("pos")) { + const QPoint savedPosition = settings.value("pos").toPoint(); + const QRect geometry = QApplication::desktop()->availableGeometry(savedPosition); + if (geometry.contains(savedPosition)) + move(savedPosition); + } + settings.endGroup(); +} + +void MainWindow::handleMessage(const QString &message) +{ + if (message.startsWith(QLatin1String("runscript "))) { + const QString filePath = message.mid(10); + scriptAdapter->run(filePath); + } +} + +void MainWindow::callDeviceScript(const DeviceData &newDevice) +{ + QString deviceScript = QCoreApplication::applicationDirPath() + + QString::fromUtf8("/scripts/devices/") + newDevice.name + + QString::fromUtf8(".qs"); + + if (!QFile::exists(deviceScript)) { + deviceScript = deviceScript.replace(newDevice.name + QString::fromUtf8(".qs"), + QString::fromUtf8("Default.qs")); + } + scriptAdapter->run(deviceScript); +} diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h new file mode 100644 index 0000000..32497ae --- /dev/null +++ b/src/ui/mainwindow.h @@ -0,0 +1,85 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H +#include "deviceitem.h" +#include <QtGui/QWidget> + +class DeviceItem; +class ApplicationManager; +class MobilityServer; +class ConfigurationWidget; +class ScriptAdapter; +class QGraphicsView; +class QGraphicsScene; + +class MainWindow : public QWidget +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + + virtual bool eventFilter(QObject *watched, QEvent *event); + virtual void closeEvent(QCloseEvent *event); + +public slots: + void setSizeToDevice(const QSize &size); + void dragFromView(const QPoint &to); + void setViewSize(const QSize &size); + + // for messages from other simulator instances + void handleMessage(const QString &message); + +private slots: + void callDeviceScript(const DeviceData &newDevice); + +private: + void writeSettings() const; + void readSettings(); + +private: + QGraphicsView *view; + QGraphicsScene *scene; + + ConfigurationWidget *config; + ApplicationManager *applicationManager; + DeviceItem *deviceItem; + + MobilityServer *mobilityServer; + + ScriptAdapter *scriptAdapter; + + QWidget *debugWindow; + bool startupError; +}; + +#endif // MAINWINDOW_H diff --git a/src/ui/menus/fremantle_landscape.png b/src/ui/menus/fremantle_landscape.png Binary files differnew file mode 100644 index 0000000..9b1de05 --- /dev/null +++ b/src/ui/menus/fremantle_landscape.png diff --git a/src/ui/menus/fremantle_portrait.png b/src/ui/menus/fremantle_portrait.png Binary files differnew file mode 100644 index 0000000..d9e12bd --- /dev/null +++ b/src/ui/menus/fremantle_portrait.png diff --git a/src/ui/menus/menus.qrc b/src/ui/menus/menus.qrc new file mode 100644 index 0000000..773d106 --- /dev/null +++ b/src/ui/menus/menus.qrc @@ -0,0 +1,10 @@ +<RCC> + <qresource prefix="/menus"> + <file>fremantle_landscape.png</file> + <file>fremantle_portrait.png</file> + <file>symbiantouch_status_landscape.png</file> + <file>symbiantouch_status_portrait.png</file> + <file>symbiantouch_buttons_small_landscape.png</file> + <file>symbiantouch_buttons_small_portrait.png</file> + </qresource> +</RCC> diff --git a/src/ui/menus/symbiantouch_buttons_small_landscape.png b/src/ui/menus/symbiantouch_buttons_small_landscape.png Binary files differnew file mode 100644 index 0000000..a3653dd --- /dev/null +++ b/src/ui/menus/symbiantouch_buttons_small_landscape.png diff --git a/src/ui/menus/symbiantouch_buttons_small_portrait.png b/src/ui/menus/symbiantouch_buttons_small_portrait.png Binary files differnew file mode 100644 index 0000000..f0f3af7 --- /dev/null +++ b/src/ui/menus/symbiantouch_buttons_small_portrait.png diff --git a/src/ui/menus/symbiantouch_status_landscape.png b/src/ui/menus/symbiantouch_status_landscape.png Binary files differnew file mode 100644 index 0000000..99a1e97 --- /dev/null +++ b/src/ui/menus/symbiantouch_status_landscape.png diff --git a/src/ui/menus/symbiantouch_status_portrait.png b/src/ui/menus/symbiantouch_status_portrait.png Binary files differnew file mode 100644 index 0000000..c9dff3e --- /dev/null +++ b/src/ui/menus/symbiantouch_status_portrait.png diff --git a/src/ui/messagingui.cpp b/src/ui/messagingui.cpp new file mode 100644 index 0000000..6ebc22e --- /dev/null +++ b/src/ui/messagingui.cpp @@ -0,0 +1,76 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "messagingui.h" + +#include "configurationwidget.h" +#include "mobilitydata.h" + +#include <remotecontrolwidget/optionsitem.h> + +#include <QtGui/QPushButton> +#include <QtGui/QFileDialog> + +MessagingUi::MessagingUi(MobilityData *mobilityData, QWidget *parent) + : ToolBoxPage(parent) + , mMobilityData(mobilityData) +{ + QList<OptionsItem *> options; + OptionsItem *item; + + QPushButton *incomingEmailButton = new QPushButton(tr("Trigger")); + item = new OptionsItem(tr("Incoming email"), incomingEmailButton); + item->addTag(tr("message")); + connect(incomingEmailButton, SIGNAL(clicked()), mobilityData, SLOT(addNewEmail())); + options += item; + + QPushButton *incomingSmsButton = new QPushButton(tr("Trigger")); + item = new OptionsItem(tr("Incoming SMS"), incomingSmsButton); + item->addTag(tr("message")); + connect(incomingSmsButton, SIGNAL(clicked()), mobilityData, SLOT(addNewSms())); + options += item; + + QPushButton *importMaildirButton = new QPushButton(tr("Import")); + item = new OptionsItem(tr("Import mail directory"), importMaildirButton); + item->addTag(tr("message")); + connect(importMaildirButton, SIGNAL(clicked()), this, SLOT(importMaildir())); + options += item; + + setTitle(tr("Messaging")); + setOptions(options); +} + +void MessagingUi::importMaildir() +{ + QString dir = QFileDialog::getExistingDirectory(0, tr("Select maildir Directory to Import")); + if (dir.isEmpty()) + return; + + mMobilityData->mMessaging->importMaildir(dir); +} diff --git a/src/ui/messagingui.h b/src/ui/messagingui.h new file mode 100644 index 0000000..372f7bf --- /dev/null +++ b/src/ui/messagingui.h @@ -0,0 +1,53 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MESSAGINGUI_H +#define MESSAGINGUI_H + +#include <remotecontrolwidget/toolbox.h> + +#include <QtCore/QObject> + +class MobilityData; +class ConfigurationWidget; + +class MessagingUi : public ToolBoxPage +{ + Q_OBJECT +public: + explicit MessagingUi(MobilityData *mobilityData, QWidget *parent = 0); + +private slots: + void importMaildir(); + +private: + MobilityData *mMobilityData; +}; + +#endif // MESSAGINGUI_H diff --git a/src/ui/sensorsui.cpp b/src/ui/sensorsui.cpp new file mode 100644 index 0000000..1710d1b --- /dev/null +++ b/src/ui/sensorsui.cpp @@ -0,0 +1,522 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "sensorsui.h" + +#include "configurationwidget.h" + +#include <QtCore/QMetaEnum> +#include <QtGui/QComboBox> +#include <QtGui/QLineEdit> +#include <QtGui/QSlider> +#include <QtGui/QDoubleValidator> +#include <QtGui/QPushButton> +#include <QtGui/QRadioButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QDateTimeEdit> +#include <qmath.h> + +SensorDoubleEdit::SensorDoubleEdit(QWidget *parent) + : QWidget(parent) + , mValue(0) + , mDecimalPlaces(0) + , mCorrectionFactor(1) +{ + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->setMargin(0); + vLayout->setSpacing(1); + mSlider = new QSlider(); + mSlider->setOrientation(Qt::Horizontal); + mSlider->setTickInterval(1); + connect(mSlider, SIGNAL(valueChanged(int)), SLOT(changeValue(int))); + mLineEdit = new QLineEdit("0.00"); + mLineEdit->setValidator(new QDoubleValidator(this)); + connect(mLineEdit, SIGNAL(editingFinished()), SLOT(updateValueFromLineEdit())); + vLayout->addWidget(mSlider); + vLayout->addWidget(mLineEdit); + setLayout(vLayout); +} + +double SensorDoubleEdit::value() const +{ + return mValue; +} + +void SensorDoubleEdit::setValue(double newValue, bool skipSignal) +{ + if (mValue != newValue) + { + mValue = newValue; + mLineEdit->setText(QString::number(newValue, 'f', mDecimalPlaces)); + int sliderPos = (int)(newValue * mCorrectionFactor); + if (mSlider->value() != sliderPos) + mSlider->setValue(sliderPos); + if (!skipSignal) + emit valueChanged(newValue); + } +} + +void SensorDoubleEdit::changeValue(int newValue) +{ + double actualValue = newValue / (double)mCorrectionFactor; + setValue(actualValue); +} + +void SensorDoubleEdit::updateValueFromLineEdit() +{ + double newValue = mLineEdit->text().toDouble(0); + if (newValue >= mRange.first && newValue <= mRange.second) + setValue(newValue); + else + mLineEdit->setText(QString::number(mValue)); +} + +void SensorDoubleEdit::setRange(double min, double max) +{ + if (mRange.first != min || mRange.second != max) { + mRange = QPair<double, double>(min, max); + updateSlider(); + } +} + +void SensorDoubleEdit::setDecimalPlaces(int places) +{ + if (mDecimalPlaces != places) { + mDecimalPlaces = places; + mCorrectionFactor = pow(10., places); + updateSlider(); + } +} + +void SensorDoubleEdit::updateSlider() +{ + mSlider->setRange(mRange.first * mCorrectionFactor, mRange.second * mCorrectionFactor); + mSlider->setValue(mValue * mCorrectionFactor); +} + +SensorsUi::SensorsUi(QWidget *parent) + : ToolBoxPage(parent) + , mAmbientLightBox(0) + , mAccelerometerXEdit(0) + , mAccelerometerYEdit(0) + , mAccelerometerZEdit(0) + , mMagnetometerXEdit(0) + , mMagnetometerYEdit(0) + , mMagnetometerZEdit(0) + , mMagnetometerCalibrationLevelEdit(0) + , mCompassCalibrationLevelEdit(0) + , mCompassAzimuthEdit(0) + , mProximitySensorCloseButton(0) + , mTimeEdit(0) +{ + mScriptInterface = new SensorsScriptInterface(this); + + QStringList tags; + QList<OptionsItem *> optionsList; + + mAmbientLightBox = new QComboBox(); + connect(mAmbientLightBox, SIGNAL(activated(int)), SLOT(emitSensorsDataChange())); + OptionsItem *item = new OptionsItem(tr("Ambient light"), mAmbientLightBox); + optionsList << item; + + mAccelerometerXEdit = new SensorDoubleEdit(); + mAccelerometerXEdit->setRange(-50, 50); + mAccelerometerXEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Accelerometer x"), mAccelerometerXEdit); + connect(mAccelerometerXEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mAccelerometerYEdit = new SensorDoubleEdit(); + mAccelerometerYEdit->setRange(-50, 50); + mAccelerometerYEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Accelerometer y"), mAccelerometerYEdit); + connect(mAccelerometerYEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mAccelerometerZEdit = new SensorDoubleEdit(); + mAccelerometerZEdit->setRange(-50, 50); + mAccelerometerZEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Accelerometer z"), mAccelerometerZEdit); + connect(mAccelerometerZEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mMagnetometerXEdit = new SensorDoubleEdit(); + mMagnetometerXEdit->setRange(0, 1); + mMagnetometerXEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Magnetometer x"), mMagnetometerXEdit); + connect(mMagnetometerXEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mMagnetometerYEdit = new SensorDoubleEdit(); + mMagnetometerYEdit->setRange(0, 1); + mMagnetometerYEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Magnetometer y"), mMagnetometerYEdit); + connect(mMagnetometerYEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mMagnetometerZEdit = new SensorDoubleEdit(); + mMagnetometerZEdit->setRange(0, 1); + mMagnetometerZEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Magnetometer z"), mMagnetometerZEdit); + connect(mMagnetometerZEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mMagnetometerCalibrationLevelEdit = new SensorDoubleEdit(); + mMagnetometerCalibrationLevelEdit->setRange(0, 1); + mMagnetometerCalibrationLevelEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Magnetometer calibration level"), mMagnetometerCalibrationLevelEdit); + connect(mMagnetometerCalibrationLevelEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mCompassAzimuthEdit = new SensorDoubleEdit(); + mCompassAzimuthEdit->setRange(0, 360); + mCompassAzimuthEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Compass azimuth"), mCompassAzimuthEdit); + connect(mCompassAzimuthEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mCompassCalibrationLevelEdit = new SensorDoubleEdit(); + mCompassCalibrationLevelEdit->setRange(0, 1); + mCompassCalibrationLevelEdit->setDecimalPlaces(2); + item = new OptionsItem(tr("Compass calibration level"), mCompassCalibrationLevelEdit); + connect(mCompassCalibrationLevelEdit, SIGNAL(valueChanged(double)), SLOT(emitSensorsDataChange())); + item->setTags(tags); + optionsList << item; + + mProximitySensorCloseButton = new QPushButton(tr("Far")); + mProximitySensorCloseButton->setCheckable(true); + item = new OptionsItem(tr("Proximity distance"), mProximitySensorCloseButton); + connect(mProximitySensorCloseButton, SIGNAL(toggled(bool)), SLOT(emitSensorsDataChange())); + connect(mProximitySensorCloseButton, SIGNAL(toggled(bool)), SLOT(updateProximityButtonText())); + item->setTags(tags); + optionsList << item; + + QHBoxLayout *radioLayout = new QHBoxLayout(); + mCurrentRadio = new QRadioButton(tr("Current")); + mCurrentRadio->setChecked(true); + mOverrideRadio = new QRadioButton(tr("Override")); + radioLayout->addWidget(mCurrentRadio); + radioLayout->addWidget(mOverrideRadio); + mTimeEdit = new QDateTimeEdit(); + mTimeEdit->setDisabled(true); + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->setContentsMargins(0, 0, 0, 0); + vLayout->addLayout(radioLayout); + vLayout->addWidget(mTimeEdit); + QWidget *tmp = new QWidget(); + tmp->setLayout(vLayout); + item = new OptionsItem(tr("Timestamp"), tmp); + item->setTags(tags << tr("Current") << tr("Override")); + optionsList << item; + connect(mCurrentRadio, SIGNAL(toggled(bool)), SLOT(updateTimeEditDisabled())); + connect(mTimeEdit, SIGNAL(dateTimeChanged(const QDateTime &)), SLOT(emitSensorsDataChange())); + + initializeAmbientLightOptions(); + + setTitle(tr("Sensors")); + setOptions(optionsList); +} + +SensorsUi::~SensorsUi() +{ +} + +SensorsScriptInterface *SensorsUi::scriptInterface() const +{ + return mScriptInterface; +} + +SensorsUi::SensorsData SensorsUi::sensorsData() const +{ + SensorsUi::SensorsData data; + data.ambientLightLevel = static_cast<SensorsScriptInterface::LightLevel>(mAmbientLightBox->currentIndex()); + data.accelerometerX = mAccelerometerXEdit->value(); + data.accelerometerY = mAccelerometerYEdit->value(); + data.accelerometerZ = mAccelerometerZEdit->value(); + data.magnetometerX = mMagnetometerXEdit->value(); + data.magnetometerY = mMagnetometerYEdit->value(); + data.magnetometerZ = mMagnetometerZEdit->value(); + data.magnetometerCalibrationLevel = mMagnetometerCalibrationLevelEdit->value(); + data.compassCalibrationLevel = mCompassCalibrationLevelEdit->value(); + data.compassAzimuth = mCompassAzimuthEdit->value(); + data.proximitySensorClose = mProximitySensorCloseButton->isChecked(); + data.useCurrentTime = mCurrentRadio->isChecked(); + data.timestamp = mTimeEdit->dateTime(); + return data; +} + +void SensorsUi::setSensorsData(const SensorsUi::SensorsData &data) +{ + setDisplayedSensorsData(data); + emit sensorsDataChanged(data); +} + +void SensorsUi::setDisplayedSensorsData(const SensorsUi::SensorsData &data) +{ + mAmbientLightBox->setCurrentIndex(data.ambientLightLevel); + mAccelerometerXEdit->setValue(data.accelerometerX); + mAccelerometerYEdit->setValue(data.accelerometerY); + mAccelerometerZEdit->setValue(data.accelerometerZ); + mMagnetometerXEdit->setValue(data.magnetometerX); + mMagnetometerYEdit->setValue(data.magnetometerY); + mMagnetometerZEdit->setValue(data.magnetometerZ); + mMagnetometerCalibrationLevelEdit->setValue(data.magnetometerCalibrationLevel); + mCompassCalibrationLevelEdit->setValue(data.compassCalibrationLevel); + mCompassAzimuthEdit->setValue(data.compassAzimuth); + mProximitySensorCloseButton->setChecked(data.proximitySensorClose); + mCurrentRadio->setChecked(data.useCurrentTime); + mTimeEdit->setDateTime(data.timestamp); +} + +void SensorsUi::emitSensorsDataChange() const +{ + emit sensorsDataChanged(sensorsData()); +} + +void SensorsUi::initializeAmbientLightOptions() +{ + mAmbientLightBox->clear(); + QStringList lightOptions; + + const QMetaObject &metaObject = SensorsScriptInterface::staticMetaObject; + int enumIndex = metaObject.indexOfEnumerator("LightLevel"); + QMetaEnum metaEnum = metaObject.enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + lightOptions.append(metaEnum.key(i)); + mAmbientLightBox->addItems(lightOptions); +} + +void SensorsUi::updateProximityButtonText() +{ + mProximitySensorCloseButton->setText(mProximitySensorCloseButton->isChecked() ? tr("Near") : tr("Far")); +} + +void SensorsUi::updateTimeEditDisabled() +{ + mTimeEdit->setDisabled(mCurrentRadio->isChecked()); +} + +/*! + \class SensorsScriptInterface + \brief Exposed as sensors. +*/ + +SensorsScriptInterface::SensorsScriptInterface(SensorsUi *ui) + : QObject(ui) + , ui(ui) +{ + int enumIndex = metaObject()->indexOfEnumerator("LightLevel"); + QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); +} + +SensorsScriptInterface::~SensorsScriptInterface() +{ +} + +void SensorsScriptInterface::setAmbientLightLevel(const LightLevel &data) +{ + int index = static_cast<int>(data); + if (ui->mAmbientLightBox->currentIndex() != index) { + ui->mAmbientLightBox->setCurrentIndex(index); + ui->emitSensorsDataChange(); + } + +} + +SensorsScriptInterface::LightLevel SensorsScriptInterface::ambientLightLevel() const +{ + SensorsScriptInterface::LightLevel lightLevel = static_cast<SensorsScriptInterface::LightLevel>(ui->mAmbientLightBox->currentIndex()); + return lightLevel; +} + +void SensorsScriptInterface::setAccelerometerX(double x) +{ + if (ui->mAccelerometerXEdit->value() != x) { + ui->mAccelerometerXEdit->setValue(x); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::accelerometerX() const +{ + return ui->mAccelerometerXEdit->value(); +} + +void SensorsScriptInterface::setAccelerometerY(double Y) +{ + if (ui->mAccelerometerYEdit->value() != Y) { + ui->mAccelerometerYEdit->setValue(Y); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::accelerometerY() const +{ + return ui->mAccelerometerYEdit->value(); +} + +void SensorsScriptInterface::setAccelerometerZ(double Z) +{ + if (ui->mAccelerometerZEdit->value() != Z) { + ui->mAccelerometerZEdit->setValue(Z); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::accelerometerZ() const +{ + return ui->mAccelerometerZEdit->value(); +} + +void SensorsScriptInterface::setMagnetometerX(double x) +{ + if (ui->mMagnetometerXEdit->value() != x) { + ui->mMagnetometerXEdit->setValue(x); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::magnetometerX() const +{ + return ui->mMagnetometerXEdit->value(); +} + +void SensorsScriptInterface::setMagnetometerY(double Y) +{ + if (ui->mMagnetometerYEdit->value() != Y) { + ui->mMagnetometerYEdit->setValue(Y); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::magnetometerY() const +{ + return ui->mMagnetometerYEdit->value(); +} + +void SensorsScriptInterface::setMagnetometerZ(double Z) +{ + if (ui->mMagnetometerZEdit->value() != Z) { + ui->mMagnetometerZEdit->setValue(Z); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::magnetometerZ() const +{ + return ui->mMagnetometerZEdit->value(); +} + +void SensorsScriptInterface::setMagnetometerCalibrationLevel(double l) +{ + if (ui->mMagnetometerCalibrationLevelEdit->value() != l) { + ui->mMagnetometerCalibrationLevelEdit->setValue(l); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::magnetometerCalibrationLevel() const +{ + return ui->mMagnetometerCalibrationLevelEdit->value(); +} + +void SensorsScriptInterface::setCompassCalibrationLevel(double l) +{ + if (ui->mCompassCalibrationLevelEdit->value() != l) { + ui->mCompassCalibrationLevelEdit->setValue(l); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::compassCalibrationLevel() const +{ + return ui->mCompassCalibrationLevelEdit->value(); +} + +void SensorsScriptInterface::setCompassAzimuth(double a) +{ + if (ui->mCompassAzimuthEdit->value() != a) { + ui->mCompassAzimuthEdit->setValue(a); + ui->emitSensorsDataChange(); + } +} + +double SensorsScriptInterface::compassAzimuth() const +{ + return ui->mCompassAzimuthEdit->value(); +} + +void SensorsScriptInterface::setProximitySensorClose(bool c) +{ + if (ui->mProximitySensorCloseButton->isChecked() != c) { + ui->mProximitySensorCloseButton->setChecked(c); + ui->emitSensorsDataChange(); + } +} + +bool SensorsScriptInterface::proximitySensorClose() const +{ + return ui->mProximitySensorCloseButton->isChecked(); +} + +void SensorsScriptInterface::setUseCurrentTimestamp(bool t) +{ + if (ui->mCurrentRadio->isChecked() != t) { + ui->mCurrentRadio->setChecked(t); + ui->emitSensorsDataChange(); + } +} + +bool SensorsScriptInterface::useCurrentTimestamp() const +{ + return ui->mCurrentRadio->isChecked(); +} + +void SensorsScriptInterface::setTimestamp(const QDateTime &t) +{ + if (ui->mTimeEdit->dateTime() != t) { + ui->mTimeEdit->setDateTime(t); + ui->emitSensorsDataChange(); + } +} + +QDateTime SensorsScriptInterface::timestamp() const +{ + return ui->mTimeEdit->dateTime(); +} diff --git a/src/ui/sensorsui.h b/src/ui/sensorsui.h new file mode 100644 index 0000000..c3c48c3 --- /dev/null +++ b/src/ui/sensorsui.h @@ -0,0 +1,231 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SENSORSUI_H +#define SENSORSUI_H + +#include <QtCore/QObject> +#include <QtCore/QDateTime> +#include <QtGui/QSlider> + +#include <remotecontrolwidget/toolbox.h> + +class ConfigurationWidget; +class Sensors; +class QComboBox; +class QLineEdit; +class QDateTimeEdit; +class QPushButton; +class QRadioButton; +class SensorsScriptInterface; + +class SensorDoubleEdit: public QWidget +{ + Q_OBJECT +public: + SensorDoubleEdit(QWidget *parent = 0); + + double value() const; + void setValue(double newValue, bool skipSignal = false); + + void setRange(double min, double max); + QPair<double, double> range() const; + + void setDecimalPlaces(int places); + int decimalPlaces() const; + +private slots: + void changeValue(int newValue); + void updateValueFromLineEdit(); + +signals: + void valueChanged(double); + +private: + double mValue; + QPair<double, double> mRange; + int mDecimalPlaces; + int mCorrectionFactor; + QSlider *mSlider; + QLineEdit *mLineEdit; + + void updateSlider(); +}; + +class SensorsUi; + +class SensorsScriptInterface : public QObject +{ + Q_OBJECT +public: + // depends on order of items + // has to match QAmbientLightReading::LightLevel + enum LightLevel { + Undefined, + Dark, + Twilight, + Light, + Bright, + Sunny + }; + Q_ENUMS(LightLevel); + + SensorsScriptInterface(SensorsUi *ui); + virtual ~SensorsScriptInterface(); + + Q_PROPERTY(LightLevel ambientLightLevel READ ambientLightLevel WRITE setAmbientLightLevel) + Q_PROPERTY(double accelerometerX READ accelerometerX WRITE setAccelerometerX) + Q_PROPERTY(double accelerometerY READ accelerometerY WRITE setAccelerometerY) + Q_PROPERTY(double accelerometerZ READ accelerometerZ WRITE setAccelerometerZ) + + Q_PROPERTY(double magnetometerX READ magnetometerX WRITE setMagnetometerX) + Q_PROPERTY(double magnetometerY READ magnetometerY WRITE setMagnetometerY) + Q_PROPERTY(double magnetometerZ READ magnetometerZ WRITE setMagnetometerZ) + Q_PROPERTY(double magnetometerCalibrationLevel READ magnetometerCalibrationLevel WRITE setMagnetometerCalibrationLevel) + + Q_PROPERTY(double compassCalibrationLevel READ compassCalibrationLevel WRITE setCompassCalibrationLevel) + Q_PROPERTY(double compassAzimuth READ compassAzimuth WRITE setCompassAzimuth) + + Q_PROPERTY(bool proximitySensorClose READ proximitySensorClose WRITE setProximitySensorClose) + + Q_PROPERTY(bool useCurrentTimestamp READ useCurrentTimestamp WRITE setUseCurrentTimestamp) + Q_PROPERTY(QDateTime timestamp READ timestamp WRITE setTimestamp) + + void setAmbientLightLevel(const LightLevel &data); + LightLevel ambientLightLevel() const; + + void setAccelerometerX(double x); + double accelerometerX() const; + + void setAccelerometerY(double y); + double accelerometerY() const; + + void setAccelerometerZ(double z); + double accelerometerZ() const; + + void setMagnetometerX(double x); + double magnetometerX() const; + + void setMagnetometerY(double y); + double magnetometerY() const; + + void setMagnetometerZ(double z); + double magnetometerZ() const; + + void setMagnetometerCalibrationLevel(double l); + double magnetometerCalibrationLevel() const; + + void setCompassCalibrationLevel(double l); + double compassCalibrationLevel() const; + + void setCompassAzimuth(double a); + double compassAzimuth() const; + + void setProximitySensorClose(bool c); + bool proximitySensorClose() const; + + void setUseCurrentTimestamp(bool t); + bool useCurrentTimestamp() const; + + void setTimestamp(const QDateTime &t); + QDateTime timestamp() const; + +private: + SensorsUi *ui; +}; + +class SensorsUi : public ToolBoxPage +{ + Q_OBJECT +public: + struct SensorsData { + int ambientLightLevel; + double accelerometerX; + double accelerometerY; + double accelerometerZ; + double magnetometerX; + double magnetometerY; + double magnetometerZ; + double magnetometerCalibrationLevel; + double compassCalibrationLevel; + double compassAzimuth; + bool proximitySensorClose; + bool useCurrentTime; + QDateTime timestamp; + }; + + explicit SensorsUi(QWidget *parent = 0); + virtual ~SensorsUi(); + + SensorsScriptInterface *scriptInterface() const; + + SensorsUi::SensorsData sensorsData() const; + +public slots: + void setSensorsData(const SensorsUi::SensorsData &data); + void setDisplayedSensorsData(const SensorsUi::SensorsData &data); + +signals: + void sensorsDataChanged(const SensorsUi::SensorsData &data) const; + +private slots: + void emitSensorsDataChange() const; + void updateTimeEditDisabled(); + void updateProximityButtonText(); + +private: + void initializeAmbientLightOptions(); + + friend class SensorsScriptInterface; + SensorsScriptInterface *mScriptInterface; + + void setTimestamp(const QDateTime &t); + QDateTime getTimestamp() const; + + QComboBox *mAmbientLightBox; + SensorDoubleEdit *mAccelerometerXEdit; + SensorDoubleEdit *mAccelerometerYEdit; + SensorDoubleEdit *mAccelerometerZEdit; + + SensorDoubleEdit *mMagnetometerXEdit; + SensorDoubleEdit *mMagnetometerYEdit; + SensorDoubleEdit *mMagnetometerZEdit; + SensorDoubleEdit *mMagnetometerCalibrationLevelEdit; + + SensorDoubleEdit *mCompassCalibrationLevelEdit; + SensorDoubleEdit *mCompassAzimuthEdit; + + QPushButton *mProximitySensorCloseButton; + + QRadioButton *mCurrentRadio; + QRadioButton *mOverrideRadio; + QDateTimeEdit *mTimeEdit; +}; + +#endif // SENSORSUI_H diff --git a/src/ui/style/images/advanced.png b/src/ui/style/images/advanced.png Binary files differnew file mode 100644 index 0000000..2a894ec --- /dev/null +++ b/src/ui/style/images/advanced.png diff --git a/src/ui/style/images/advanced_light.png b/src/ui/style/images/advanced_light.png Binary files differnew file mode 100644 index 0000000..b32829f --- /dev/null +++ b/src/ui/style/images/advanced_light.png diff --git a/src/ui/style/images/battery_0.png b/src/ui/style/images/battery_0.png Binary files differnew file mode 100644 index 0000000..eb4d1e8 --- /dev/null +++ b/src/ui/style/images/battery_0.png diff --git a/src/ui/style/images/battery_100.png b/src/ui/style/images/battery_100.png Binary files differnew file mode 100644 index 0000000..de8c2e9 --- /dev/null +++ b/src/ui/style/images/battery_100.png diff --git a/src/ui/style/images/battery_20.png b/src/ui/style/images/battery_20.png Binary files differnew file mode 100644 index 0000000..4048b36 --- /dev/null +++ b/src/ui/style/images/battery_20.png diff --git a/src/ui/style/images/battery_40.png b/src/ui/style/images/battery_40.png Binary files differnew file mode 100644 index 0000000..71e4e09 --- /dev/null +++ b/src/ui/style/images/battery_40.png diff --git a/src/ui/style/images/battery_60.png b/src/ui/style/images/battery_60.png Binary files differnew file mode 100644 index 0000000..2562a3e --- /dev/null +++ b/src/ui/style/images/battery_60.png diff --git a/src/ui/style/images/battery_80.png b/src/ui/style/images/battery_80.png Binary files differnew file mode 100644 index 0000000..6947b1f --- /dev/null +++ b/src/ui/style/images/battery_80.png diff --git a/src/ui/style/images/batterypower.png b/src/ui/style/images/batterypower.png Binary files differnew file mode 100644 index 0000000..67d15e4 --- /dev/null +++ b/src/ui/style/images/batterypower.png diff --git a/src/ui/style/images/closebutton.png b/src/ui/style/images/closebutton.png Binary files differnew file mode 100644 index 0000000..6eea001 --- /dev/null +++ b/src/ui/style/images/closebutton.png diff --git a/src/ui/style/images/connection.png b/src/ui/style/images/connection.png Binary files differnew file mode 100644 index 0000000..2a0577d --- /dev/null +++ b/src/ui/style/images/connection.png diff --git a/src/ui/style/images/favoriteScripts.png b/src/ui/style/images/favoriteScripts.png Binary files differnew file mode 100644 index 0000000..1348354 --- /dev/null +++ b/src/ui/style/images/favoriteScripts.png diff --git a/src/ui/style/images/network.png b/src/ui/style/images/network.png Binary files differnew file mode 100644 index 0000000..13e7c09 --- /dev/null +++ b/src/ui/style/images/network.png diff --git a/src/ui/style/images/networkstatus.png b/src/ui/style/images/networkstatus.png Binary files differnew file mode 100644 index 0000000..9173c65 --- /dev/null +++ b/src/ui/style/images/networkstatus.png diff --git a/src/ui/style/images/phone.png b/src/ui/style/images/phone.png Binary files differnew file mode 100644 index 0000000..0ea8fbb --- /dev/null +++ b/src/ui/style/images/phone.png diff --git a/src/ui/style/images/reset.png b/src/ui/style/images/reset.png Binary files differnew file mode 100644 index 0000000..cc0d6a2 --- /dev/null +++ b/src/ui/style/images/reset.png diff --git a/src/ui/style/images/unknownpower.png b/src/ui/style/images/unknownpower.png Binary files differnew file mode 100644 index 0000000..e09005c --- /dev/null +++ b/src/ui/style/images/unknownpower.png diff --git a/src/ui/style/images/wall.png b/src/ui/style/images/wall.png Binary files differnew file mode 100644 index 0000000..3845fc3 --- /dev/null +++ b/src/ui/style/images/wall.png diff --git a/src/ui/style/images/wall_charge.png b/src/ui/style/images/wall_charge.png Binary files differnew file mode 100644 index 0000000..85caf66 --- /dev/null +++ b/src/ui/style/images/wall_charge.png diff --git a/src/ui/systeminfogenericui.cpp b/src/ui/systeminfogenericui.cpp new file mode 100644 index 0000000..68cd020 --- /dev/null +++ b/src/ui/systeminfogenericui.cpp @@ -0,0 +1,928 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "systeminfogenericui.h" + +#include <QtCore/QMetaEnum> +#include <QtGui/QPushButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QComboBox> +#include <QtGui/QCheckBox> +#include <QtGui/QLabel> +#include <QtGui/QSpinBox> +#include <QtGui/QFormLayout> +#include <QtGui/QGroupBox> +#include <QtGui/QInputDialog> + +GenericSystemInfoUi::GenericSystemInfoUi(QWidget *parent) + : ToolBoxPage(parent) +{ + mScriptInterface = new GenericSystemInfoScriptInterface(this); + + initializeGeneric(); + + // button translators + connect(this, SIGNAL(genericDataChanged(GenericSystemInfoUi::GenericData)), SLOT(emitButtonSignalsOnChange())); +} + +void GenericSystemInfoUi::initializeGeneric() +{ + QStringList tags; + QList<OptionsItem *> optionsList; + tags << tr("generic"); + + systemInfoBatteryLevel = new QSpinBox(); + systemInfoBatteryLevel->setRange(0, 100); + systemInfoBatteryStatus = new QLabel(); + systemInfoBatteryStatus->setAlignment(Qt::AlignHCenter); + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->setContentsMargins(0, 0, 0, 0); + vLayout->addWidget(systemInfoBatteryLevel); + vLayout->addWidget(systemInfoBatteryStatus); + QWidget *tmp = new QWidget(); + tmp->setContentsMargins(0, 0, 0, 0); + tmp->setLayout(vLayout); + connect(systemInfoBatteryLevel, SIGNAL(valueChanged(int)), SLOT(sysinfoUpdateBatteryStatus(int))); + connect(systemInfoBatteryLevel, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + OptionsItem *item = new OptionsItem(tr("Battery level"), tmp); + optionsList << item; + + systemInfoPowerState = new QComboBox(); + connect(systemInfoPowerState, SIGNAL(activated(int)), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Power state"), systemInfoPowerState); + optionsList << item; + + systemInfoProfile = new QComboBox(); + connect(systemInfoProfile, SIGNAL(activated(int)), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Profile"), systemInfoProfile); + optionsList << item; + + systemInfoDeviceLocked = new QCheckBox(); + connect(systemInfoDeviceLocked, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Device locked"), systemInfoDeviceLocked); + optionsList << item; + + systemInfoLanguage = new QLineEdit(); + systemInfoLanguage->setInputMask("<AA"); + systemInfoLanguage->setValidator(new QRegExpValidator(QRegExp("\\S\\S"), systemInfoLanguage)); + connect(systemInfoLanguage, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Language"), systemInfoLanguage); + item->setAdvanced(); + item->setTags(tags); + optionsList << item; + + systemInfoCountryCode = new QLineEdit(); + systemInfoCountryCode->setInputMask(">AA"); + systemInfoCountryCode->setValidator(new QRegExpValidator(QRegExp("\\S\\S"), systemInfoCountryCode)); + connect(systemInfoCountryCode, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Country code"), systemInfoCountryCode); + item->setAdvanced(); + optionsList << item; + + systemInfoAvailableLanguages = new QComboBox(); + QPushButton *systemInfoAddAvailableLanguage = new QPushButton(tr("Add")); + QPushButton *systemInfoRemoveAvailableLanguage = new QPushButton(tr("Remove")); + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->setContentsMargins(0, 0, 0, 0); + hLayout->addWidget(systemInfoAvailableLanguages); + hLayout->addWidget(systemInfoAddAvailableLanguage); + hLayout->addWidget(systemInfoRemoveAvailableLanguage); + QGroupBox *systemInfoLanguageGroupBox = new QGroupBox(); + systemInfoLanguageGroupBox->setLayout(hLayout); + QPushButton *toggleLanguagesVisible = new QPushButton(tr("Show")); + connect(systemInfoRemoveAvailableLanguage, SIGNAL(clicked()), SLOT(sysinfoRemoveAvailableLanguage())); + connect(systemInfoAddAvailableLanguage, SIGNAL(clicked()), SLOT(sysinfoAddAvailableLanguage())); + item = new OptionsItem(tr("Available languages"), toggleLanguagesVisible); + item->setTags(tags); + item->setAdvanced(); + OptionsItem *advancedItem = new OptionsItem("", systemInfoLanguageGroupBox, true); + item->setAdvancedPage(advancedItem); + optionsList << item; + + systemInfoFeatures = new QComboBox(); + systemInfoFeatureEnabled = new QLabel(tr("available")); + QPushButton *systemInfoToggleFeature = new QPushButton(tr("Toggle")); + hLayout = new QHBoxLayout(); + hLayout->setContentsMargins(0, 0, 0, 0); + hLayout->addWidget(systemInfoFeatures); + hLayout->addWidget(systemInfoFeatureEnabled); + hLayout->addWidget(systemInfoToggleFeature); + QGroupBox *systemInfoFeaturesGroupBox = new QGroupBox(); + systemInfoFeaturesGroupBox->setLayout(hLayout); + QPushButton *toggleFeaturesVisible = new QPushButton(tr("Show")); + connect(systemInfoToggleFeature, SIGNAL(clicked()), this, SLOT(sysinfoToggleFeature())); + connect(systemInfoFeatures, SIGNAL(activated(int)), this, SLOT(sysinfoDisplayFeature())); + item = new OptionsItem(tr("Features"), toggleFeaturesVisible); + QStringList featureTags = tags; + featureTags << tr("Bluetooth") << tr("Camera") << tr("FM Radio") << tr("Infrared"); + featureTags << tr("LED") << tr("Memory Card") << tr("USB") << tr("Vibration"); + featureTags << tr("WLAN") << tr("SIM") << tr("Location") << tr("Video out") << tr("Haptics"); + item->setTags(featureTags); + item->setAdvanced(); + advancedItem = new OptionsItem("", systemInfoFeaturesGroupBox, true); + item->setAdvancedPage(advancedItem); + optionsList << item; + + systemInfoVersions = new QComboBox(); + systemInfoVersionString = new QLabel(tr("version text")); + QPushButton *systemInfoChangeVersion = new QPushButton(tr("Change")); + hLayout = new QHBoxLayout(); + hLayout->setContentsMargins(0, 0, 0, 0); + hLayout->addWidget(systemInfoVersions); + hLayout->addWidget(systemInfoVersionString); + hLayout->addWidget(systemInfoChangeVersion); + QGroupBox *systemInfoVersionsGroupBox = new QGroupBox(); + systemInfoVersionsGroupBox->setLayout(hLayout); + QPushButton *toggleVersionsVisible = new QPushButton(tr("Show")); + connect(systemInfoChangeVersion, SIGNAL(clicked()), SLOT(sysinfoChangeVersion())); + connect(systemInfoVersions, SIGNAL(activated(int)), SLOT(sysinfoDisplayVersion())); + item = new OptionsItem(tr("Versions"), toggleVersionsVisible); + QStringList versionTags = tags; + versionTags << "os" << "qt" << "firmware"; + item->setTags(versionTags); + item->setAdvanced(); + advancedItem = new OptionsItem("", systemInfoVersionsGroupBox, true); + item->setAdvancedPage(advancedItem); + optionsList << item; + + tags.removeAll(tr("generic")); + tags << tr("device"); + + systemInfoSimStatus = new QComboBox(); + connect(systemInfoSimStatus, SIGNAL(activated(int)), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("SIM Status"), systemInfoSimStatus); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + systemInfoImei = new QLineEdit(); + systemInfoImei->setInputMask("99-999999-999999-9"); + systemInfoImei->setValidator(new QRegExpValidator(QRegExp("\\d{2}-\\d{6}-\\d{6}-\\d"), systemInfoImei)); + connect(systemInfoImei, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("IMEI"), systemInfoImei); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + systemInfoImsi = new QLineEdit(); + systemInfoImsi->setInputMask("999999999999990"); + systemInfoImsi->setValidator(new QRegExpValidator(QRegExp("\\d{14}[\\d\\s]?"), systemInfoImsi)); + connect(systemInfoImsi, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("IMSI"), systemInfoImsi); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + systemInfoInputKeys = new QCheckBox(tr("Keys")); + systemInfoInputKeypad = new QCheckBox(tr("Keypad")); + systemInfoInputKeyboard = new QCheckBox(tr("Keyboard")); + systemInfoInputSingleTouch = new QCheckBox(tr("Single touch")); + systemInfoInputMultiTouch = new QCheckBox(tr("Multitouch")); + systemInfoInputMouse = new QCheckBox(tr("Mouse")); + QGridLayout *gridLayout = new QGridLayout(); + gridLayout->addWidget(systemInfoInputKeys, 0, 0); + gridLayout->addWidget(systemInfoInputKeypad, 0, 1); + gridLayout->addWidget(systemInfoInputKeyboard, 0, 2); + gridLayout->addWidget(systemInfoInputSingleTouch, 1, 0); + gridLayout->addWidget(systemInfoInputMultiTouch, 1, 1); + gridLayout->addWidget(systemInfoInputMouse, 1, 2); + QGroupBox *systemInfoInputGroupBox = new QGroupBox; + systemInfoInputGroupBox->setLayout(gridLayout); + QPushButton *toggleInputMethodsVisible = new QPushButton(tr("Show")); + connect(systemInfoInputKeys, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + connect(systemInfoInputKeypad, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + connect(systemInfoInputKeyboard, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + connect(systemInfoInputSingleTouch, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + connect(systemInfoInputMultiTouch, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + connect(systemInfoInputMouse, SIGNAL(clicked()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Input methods"), toggleInputMethodsVisible); + QStringList inputTags = tags; + inputTags << tr("keys") << tr("keypad") << tr("keyboard") << tr("single"); + inputTags << tr("multi") << tr("touch") << tr("mouse"); + item->setTags(inputTags); + item->setAdvanced(); + advancedItem = new OptionsItem("", systemInfoInputGroupBox, true); + item->setAdvancedPage(advancedItem); + optionsList << item; + + systemInfoManufacturer = new QLineEdit(); + connect(systemInfoManufacturer, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Manufacturer"), systemInfoManufacturer); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + systemInfoModel = new QLineEdit(); + connect(systemInfoModel, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Model"), systemInfoModel); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + systemInfoProductName = new QLineEdit(); + connect(systemInfoProductName, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Product name"), systemInfoProductName); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + tags.removeAll(tr("device")); + tags << tr("display"); + + systemInfoColorDepth = new QSpinBox(); + systemInfoColorDepth->setRange(8, 32); + systemInfoColorDepth->setValue(32); + systemInfoColorDepth->setSingleStep(8); + connect(systemInfoColorDepth, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Color depth"), systemInfoColorDepth); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + systemInfoBrightness = new QSpinBox(); + systemInfoBrightness->setRange(1, 100); + connect(systemInfoBrightness, SIGNAL(editingFinished()), SLOT(emitGenericDataChanged())); + item = new OptionsItem(tr("Brightness"), systemInfoBrightness); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + + /* ### TODO: Implement. + tags.removeAll(tr("display")); + tags << tr("screen") << tr("saver") << tr("screensaver"); + + QCheckBox *screenSaverInhibited = new QCheckBox(); + item = new OptionsItem(tr("Screen saver inhibited"), screenSaverInhibited); + item->setTags(tags); + item->setAdvanced(); + optionsList << item; + */ + + initializeGenericOptions(); + initializeDeviceOptions(); + + setTitle(tr("Generic")); + setOptions(optionsList); +} + +GenericSystemInfoUi::~GenericSystemInfoUi() +{ +} + +void GenericSystemInfoUi::initializeGenericOptions() +{ + systemInfoVersions->clear(); + systemInfoVersions->addItem(tr("Operating System"), GenericSystemInfoScriptInterface::Os); + systemInfoVersions->addItem(tr("Qt"), GenericSystemInfoScriptInterface::QtCore); + systemInfoVersions->addItem(tr("Firmware"), GenericSystemInfoScriptInterface::Firmware); + sysinfoDisplayVersion(); + + systemInfoFeatures->clear(); + systemInfoFeatures->addItem(tr("Bluetooth"), GenericSystemInfoScriptInterface::BluetoothFeature); + systemInfoFeatures->addItem(tr("Camera"), GenericSystemInfoScriptInterface::CameraFeature); + systemInfoFeatures->addItem(tr("FM Radio"), GenericSystemInfoScriptInterface::FmradioFeature); + systemInfoFeatures->addItem(tr("Infrared"), GenericSystemInfoScriptInterface::IrFeature); + systemInfoFeatures->addItem(tr("LED"), GenericSystemInfoScriptInterface::LedFeature); + systemInfoFeatures->addItem(tr("Memory Card"), GenericSystemInfoScriptInterface::MemcardFeature); + systemInfoFeatures->addItem(tr("USB"), GenericSystemInfoScriptInterface::UsbFeature); + systemInfoFeatures->addItem(tr("Vibration"), GenericSystemInfoScriptInterface::VibFeature); + systemInfoFeatures->addItem(tr("WLAN"), GenericSystemInfoScriptInterface::WlanFeature); + systemInfoFeatures->addItem(tr("SIM"), GenericSystemInfoScriptInterface::SimFeature); + systemInfoFeatures->addItem(tr("Location"), GenericSystemInfoScriptInterface::LocationFeature); + systemInfoFeatures->addItem(tr("Video out"), GenericSystemInfoScriptInterface::VideoOutFeature); + systemInfoFeatures->addItem(tr("Haptics"), GenericSystemInfoScriptInterface::HapticsFeature); + sysinfoDisplayFeature(); +} + +void GenericSystemInfoUi::initializeDeviceOptions() +{ + systemInfoPowerState->clear(); + QStringList powerStates; + // depends on order of items + powerStates.append(tr("Unknown or Error")); + powerStates.append(tr("Battery")); + powerStates.append(tr("Wall")); + powerStates.append(tr("Wall and Charging")); + systemInfoPowerState->addItems(powerStates); + + systemInfoProfile->clear(); + QStringList profiles; + // depends on order of items + profiles.append(tr("Unknown or Error")); + profiles.append(tr("Silent")); + profiles.append(tr("Normal")); + profiles.append(tr("Loud")); + profiles.append(tr("Vibrate")); + profiles.append(tr("Offline")); + profiles.append(tr("Powersave")); + profiles.append(tr("Custom")); + systemInfoProfile->addItems(profiles); + + systemInfoSimStatus->clear(); + QStringList simStates; + // depends on order of items + simStates.append(tr("Not Available")); + simStates.append(tr("Single")); + simStates.append(tr("Dual")); + simStates.append(tr("Locked")); + systemInfoSimStatus->addItems(simStates); +} + +GenericSystemInfoUi::GenericData::GenericData() + : features(13) + , versions(4) +{ +} + + +void GenericSystemInfoUi::sysinfoAddAvailableLanguage() +{ + QString newLang = QInputDialog::getText(0, + "Add New Language", "Enter the new available language:"); + if (!newLang.isEmpty()) { + systemInfoAvailableLanguages->addItem(newLang); + emitGenericDataChanged(); + } +} + +void GenericSystemInfoUi::sysinfoRemoveAvailableLanguage() +{ + systemInfoAvailableLanguages->removeItem(systemInfoAvailableLanguages->currentIndex()); + emitGenericDataChanged(); +} + +void GenericSystemInfoUi::sysinfoToggleFeature() +{ + GenericSystemInfoScriptInterface::Feature currentFeature + = static_cast<GenericSystemInfoScriptInterface::Feature>(systemInfoFeatures->currentIndex()); + mFeatures[currentFeature] ^= 1; + sysinfoDisplayFeature(); + emitGenericDataChanged(); +} + +void GenericSystemInfoUi::sysinfoChangeVersion() +{ + GenericSystemInfoScriptInterface::Version v = static_cast<GenericSystemInfoScriptInterface::Version>(systemInfoVersions->itemData(systemInfoVersions->currentIndex()).toInt()); + QString newVersion = QInputDialog::getText(0, + "Change Version", "Enter the new version string:", + QLineEdit::Normal, mVersions.value(v)); + if (!newVersion.isEmpty()) { + mVersions[v] = newVersion; + sysinfoDisplayVersion(); + emitGenericDataChanged(); + } +} + +void GenericSystemInfoUi::sysinfoDisplayVersion() +{ + GenericSystemInfoScriptInterface::Version v = static_cast<GenericSystemInfoScriptInterface::Version>(systemInfoVersions->itemData(systemInfoVersions->currentIndex()).toInt()); + systemInfoVersionString->setText(mVersions.value(v)); +} + +void GenericSystemInfoUi::sysinfoDisplayFeature() +{ + GenericSystemInfoScriptInterface::Feature f = static_cast<GenericSystemInfoScriptInterface::Feature>(systemInfoFeatures->itemData(systemInfoFeatures->currentIndex()).toInt()); + if (mFeatures.value(f)) + systemInfoFeatureEnabled->setText("Available"); + else + systemInfoFeatureEnabled->setText("Not Available"); +} + +void GenericSystemInfoUi::sysinfoSetAvailableLanguages(const QStringList &list) +{ + systemInfoAvailableLanguages->clear(); + systemInfoAvailableLanguages->addItems(list); + emitGenericDataChanged(); +} + +void GenericSystemInfoUi::emitGenericDataChanged() +{ + emit genericDataChanged(genericData()); +} + +GenericSystemInfoUi::GenericData GenericSystemInfoUi::genericData() const +{ + GenericData data; + data.currentLanguage = systemInfoLanguage->text(); + data.availableLanguages.clear(); + for (int i = 0; i < systemInfoAvailableLanguages->count(); i++) + data.availableLanguages.append(systemInfoAvailableLanguages->itemText(i)); + data.currentCountryCode = systemInfoCountryCode->text(); + data.displayBrightness = systemInfoBrightness->value(); + data.colorDepth = systemInfoColorDepth->value(); + data.profile = static_cast<GenericSystemInfoScriptInterface::Profile>(systemInfoProfile->currentIndex()); + data.currentPowerState = static_cast<GenericSystemInfoScriptInterface::PowerState>(systemInfoPowerState->currentIndex()); + data.simStatus = static_cast<GenericSystemInfoScriptInterface::SimStatus>(systemInfoSimStatus->currentIndex()); + GenericSystemInfoScriptInterface::InputMethodFlags iflags; + if (systemInfoInputKeys->isChecked()) + iflags |= GenericSystemInfoScriptInterface::Keys; + if (systemInfoInputKeypad->isChecked()) + iflags |= GenericSystemInfoScriptInterface::Keypad; + if (systemInfoInputKeyboard->isChecked()) + iflags |= GenericSystemInfoScriptInterface::Keyboard; + if (systemInfoInputSingleTouch->isChecked()) + iflags |= GenericSystemInfoScriptInterface::SingleTouch; + if (systemInfoInputMultiTouch->isChecked()) + iflags |= GenericSystemInfoScriptInterface::MultiTouch; + if (systemInfoInputMouse->isChecked()) + iflags |= GenericSystemInfoScriptInterface::Mouse; + data.inputFlags = iflags; + data.imei = systemInfoImei->text(); + data.imsi = systemInfoImsi->text(); + data.manufacturer = systemInfoManufacturer->text(); + data.model = systemInfoModel->text(); + data.productName = systemInfoProductName->text(); + data.deviceLocked = systemInfoDeviceLocked->isChecked(); + data.batteryLevel = systemInfoBatteryLevel->value(); + data.features = mFeatures; + data.versions = mVersions; + return data; +} + +GenericSystemInfoScriptInterface *GenericSystemInfoUi::scriptInterface() +{ + return mScriptInterface; +} + +void GenericSystemInfoUi::sysinfoUpdateBatteryStatus(int level) +{ + // batteryButton->updateIcon(level); + if (level > 100) + systemInfoBatteryStatus->setText("No battery level"); + else if (level > 40) + systemInfoBatteryStatus->setText("Battery normal"); + else if (level > 10) + systemInfoBatteryStatus->setText("Battery low"); + else if (level > 3) + systemInfoBatteryStatus->setText("Battery very low"); + else if (level >= 0) + systemInfoBatteryStatus->setText("Battery critical"); + else // negative + systemInfoBatteryStatus->setText("No battery level"); +} + +void GenericSystemInfoUi::setGenericData(const GenericSystemInfoUi::GenericData &data) +{ + setDisplayedGenericData(data); + emit genericDataChanged(data); +} + +void GenericSystemInfoUi::setDisplayedGenericData(const GenericSystemInfoUi::GenericData &data) +{ + systemInfoAvailableLanguages->clear(); + foreach (const QString &language, data.availableLanguages) + systemInfoAvailableLanguages->addItem(language); + systemInfoBatteryLevel->setValue(data.batteryLevel); + systemInfoBrightness->setValue(data.displayBrightness); + systemInfoColorDepth->setValue(data.colorDepth); + systemInfoCountryCode->setText(data.currentCountryCode); + systemInfoDeviceLocked->setChecked(data.deviceLocked); + mFeatures = data.features; + mScriptInterface->setInputMethod(data.inputFlags); + systemInfoImei->setText(data.imei); + systemInfoImsi->setText(data.imsi); + systemInfoManufacturer->setText(data.manufacturer); + systemInfoModel->setText(data.model); + systemInfoPowerState->setCurrentIndex(static_cast<int>(data.currentPowerState)); + systemInfoLanguage->setText(data.currentLanguage); + systemInfoProductName->setText(data.productName); + systemInfoProfile->setCurrentIndex(static_cast<int>(data.profile)); + systemInfoSimStatus->setCurrentIndex(static_cast<int>(data.simStatus)); + mVersions = data.versions; +} + +void GenericSystemInfoUi::setCurrentPowerState(PowerButton::PowerState powerState) +{ + mScriptInterface->setCurrentPowerState(static_cast<GenericSystemInfoScriptInterface::PowerState>(powerState)); +} + +void GenericSystemInfoUi::setCurrentBatteryLevel(BatteryButton::BatteryLevel batteryLevel) +{ + switch (batteryLevel) { + case BatteryButton::BatteryCritical: + mScriptInterface->setBatteryLevel(3); + break; + case BatteryButton::BatteryVeryLow: + mScriptInterface->setBatteryLevel(10); + break; + case BatteryButton::BatteryLow: + mScriptInterface->setBatteryLevel(40); + break; + case BatteryButton::BatteryNormal: + mScriptInterface->setBatteryLevel(100); + break; + default: + mScriptInterface->setBatteryLevel(0); + break; + } +} + +void GenericSystemInfoUi::emitButtonSignalsOnChange() +{ + GenericSystemInfoScriptInterface::PowerState currentState = mScriptInterface->currentPowerState(); + emit currentPowerStateChanged(static_cast<PowerButton::PowerState>(currentState)); + + int currentLevel = mScriptInterface->batteryLevel(); + if (currentLevel <= 3) + emit currentBatteryLevelChanged(BatteryButton::BatteryCritical); + else if (currentLevel <= 10) + emit currentBatteryLevelChanged(BatteryButton::BatteryVeryLow); + else if (currentLevel <= 40) + emit currentBatteryLevelChanged(BatteryButton::BatteryLow); + else + emit currentBatteryLevelChanged(BatteryButton::BatteryNormal); +} + + +/*! + \class GenericSystemInfoScriptInterface + \brief Exposed as sysinfo.generic. +*/ + +GenericSystemInfoScriptInterface::GenericSystemInfoScriptInterface(GenericSystemInfoUi *ui) + : QObject(ui) + , ui(ui) +{ + int enumIndex = metaObject()->indexOfEnumerator("Version"); + QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("Feature"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("BatteryStatus"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("PowerState"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("InputMethod"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("Profile"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("SimStatus"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); +} + +GenericSystemInfoScriptInterface::~GenericSystemInfoScriptInterface() +{ +} + +QString GenericSystemInfoScriptInterface::currentLanguage() const +{ + return ui->systemInfoLanguage->text(); +} + +QStringList GenericSystemInfoScriptInterface::availableLanguages() const +{ + QStringList returnList; + for (int i = 0; i < ui->systemInfoAvailableLanguages->count(); i++) + returnList.append(ui->systemInfoAvailableLanguages->itemText(i)); + return returnList; +} + +QString GenericSystemInfoScriptInterface::currentCountryCode() const +{ + return ui->systemInfoCountryCode->text(); +} + +bool GenericSystemInfoScriptInterface::hasFeature(GenericSystemInfoScriptInterface::Feature f) const +{ + return (ui->mFeatures.contains(f) && ui->mFeatures.value(f)); +} + +QString GenericSystemInfoScriptInterface::version(GenericSystemInfoScriptInterface::Version v, const QString ¶m) const +{ + Q_UNUSED(param); + return ui->mVersions[v]; +} + +int GenericSystemInfoScriptInterface::displayBrightness(int screen) const +{ + Q_UNUSED(screen); + return ui->systemInfoBrightness->text().toInt(); +} + +int GenericSystemInfoScriptInterface::colorDepth(int screen) const +{ + Q_UNUSED(screen); + return ui->systemInfoColorDepth->text().toInt(); +} + +GenericSystemInfoScriptInterface::Profile GenericSystemInfoScriptInterface::currentProfile() const +{ + return static_cast<GenericSystemInfoScriptInterface::Profile>(ui->systemInfoProfile->currentIndex()); +} + +GenericSystemInfoScriptInterface::PowerState GenericSystemInfoScriptInterface::currentPowerState() const +{ + return static_cast<GenericSystemInfoScriptInterface::PowerState>(ui->systemInfoPowerState->currentIndex()); +} + +GenericSystemInfoScriptInterface::SimStatus GenericSystemInfoScriptInterface::simStatus() const +{ + return static_cast<GenericSystemInfoScriptInterface::SimStatus>(ui->systemInfoSimStatus->currentIndex()); +} + +GenericSystemInfoScriptInterface::InputMethodFlags GenericSystemInfoScriptInterface::inputMethod() const +{ + GenericSystemInfoScriptInterface::InputMethodFlags flags; + if (ui->systemInfoInputKeys->isChecked()) + flags |= GenericSystemInfoScriptInterface::Keys; + if (ui->systemInfoInputKeypad->isChecked()) + flags |= GenericSystemInfoScriptInterface::Keypad; + if (ui->systemInfoInputKeyboard->isChecked()) + flags |= GenericSystemInfoScriptInterface::Keyboard; + if (ui->systemInfoInputSingleTouch->isChecked()) + flags |= GenericSystemInfoScriptInterface::SingleTouch; + if (ui->systemInfoInputMultiTouch->isChecked()) + flags |= GenericSystemInfoScriptInterface::MultiTouch; + if (ui->systemInfoInputMouse->isChecked()) + flags |= GenericSystemInfoScriptInterface::Mouse; + return flags; +} + +QString GenericSystemInfoScriptInterface::imei() const +{ + return ui->systemInfoImei->text(); +} + +QString GenericSystemInfoScriptInterface::imsi() const +{ + return ui->systemInfoImsi->text(); +} + +QString GenericSystemInfoScriptInterface::manufacturer() const +{ + return ui->systemInfoManufacturer->text(); +} + +QString GenericSystemInfoScriptInterface::model() const +{ + return ui->systemInfoModel->text(); +} + +QString GenericSystemInfoScriptInterface::productName() const +{ + return ui->systemInfoProductName->text(); +} + +int GenericSystemInfoScriptInterface::batteryLevel() const +{ + return ui->systemInfoBatteryLevel->value(); +} + +bool GenericSystemInfoScriptInterface::isDeviceLocked() const +{ + return (ui->systemInfoDeviceLocked->isChecked()); +} + +GenericSystemInfoScriptInterface::BatteryStatus GenericSystemInfoScriptInterface::batteryStatus() const +{ + if (ui->systemInfoBatteryLevel->value() < 0) + return GenericSystemInfoScriptInterface::NoBatteryLevel; + else if (ui->systemInfoBatteryLevel->value() <= 3) + return GenericSystemInfoScriptInterface::BatteryCritical; + else if (ui->systemInfoBatteryLevel->value() <= 10) + return GenericSystemInfoScriptInterface::BatteryVeryLow; + else if (ui->systemInfoBatteryLevel->value() <= 40) + return GenericSystemInfoScriptInterface::BatteryLow; + else if (ui->systemInfoBatteryLevel->value() <= 100) + return GenericSystemInfoScriptInterface::BatteryNormal; + else + return GenericSystemInfoScriptInterface::NoBatteryLevel; +} + +void GenericSystemInfoScriptInterface::setCurrentLanguage(const QString &v) +{ + if (ui->systemInfoLanguage->text() != v) { + ui->systemInfoLanguage->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setCurrentCountryCode(const QString &v) +{ + if (ui->systemInfoCountryCode->text() != v) { + ui->systemInfoCountryCode->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setAvailableLanguages(const QStringList &v) +{ + ui->systemInfoAvailableLanguages->clear(); + foreach(const QString &language, v) + ui->systemInfoAvailableLanguages->addItem(language); + ui->emitGenericDataChanged(); +} + +void GenericSystemInfoScriptInterface::addAvailableLanguage(const QString &v) +{ + ui->systemInfoAvailableLanguages->addItem(v); + ui->emitGenericDataChanged(); +} + +bool GenericSystemInfoScriptInterface::removeAvailableLanguage(const QString &v) +{ + bool retValue = false; + for (int i = 0; i < ui->systemInfoAvailableLanguages->count(); i++) { + if (ui->systemInfoAvailableLanguages->itemText(i) == v) { + ui->systemInfoAvailableLanguages->removeItem(i); + i--; + retValue = true; + } + } + if (retValue) + ui->emitGenericDataChanged(); + return retValue; +} + +void GenericSystemInfoScriptInterface::removeAllAvailableLanguages() +{ + ui->systemInfoAvailableLanguages->clear(); + ui->emitGenericDataChanged(); +} + +void GenericSystemInfoScriptInterface::setFeature(GenericSystemInfoScriptInterface::Feature f, bool enabled) +{ + ui->mFeatures[f] = enabled; + ui->sysinfoDisplayFeature(); + ui->emitGenericDataChanged(); +} + +void GenericSystemInfoScriptInterface::setVersion(GenericSystemInfoScriptInterface::Version v, const QString &to) +{ + ui->mVersions[v] = to; + ui->sysinfoDisplayVersion(); + ui->emitGenericDataChanged(); +} + +void GenericSystemInfoScriptInterface::setDisplayBrightness(int brightness) +{ + if (ui->systemInfoBrightness->value() != brightness) { + ui->systemInfoBrightness->setValue(brightness); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setColorDepth(int depth) +{ + if (ui->systemInfoColorDepth->value() != depth) { + ui->systemInfoColorDepth->setValue(depth); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setCurrentProfile(GenericSystemInfoScriptInterface::Profile v) +{ + int index = static_cast<int>(v); + if (ui->systemInfoProfile->currentIndex() != index) { + ui->systemInfoProfile->setCurrentIndex(index); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setCurrentPowerState(GenericSystemInfoScriptInterface::PowerState v) +{ + int index = static_cast<int>(v); + if (ui->systemInfoPowerState->currentIndex() != index) { + ui->systemInfoPowerState->setCurrentIndex(index); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setSimStatus(GenericSystemInfoScriptInterface::SimStatus v) +{ + int index = static_cast<int>(v); + if (ui->systemInfoSimStatus->currentIndex() != index) { + ui->systemInfoSimStatus->setCurrentIndex(index); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setInputMethod(GenericSystemInfoScriptInterface::InputMethodFlags v) +{ + if (v & GenericSystemInfoScriptInterface::Keys) + ui->systemInfoInputKeys->setChecked(true); + else + ui->systemInfoInputKeys->setChecked(false); + if (v & GenericSystemInfoScriptInterface::Keypad) + ui->systemInfoInputKeypad->setChecked(true); + else + ui->systemInfoInputKeypad->setChecked(false); + if (v & GenericSystemInfoScriptInterface::Keyboard) + ui->systemInfoInputKeyboard->setChecked(true); + else + ui->systemInfoInputKeyboard->setChecked(false); + if (v & GenericSystemInfoScriptInterface::SingleTouch) + ui->systemInfoInputSingleTouch->setChecked(true); + else + ui->systemInfoInputSingleTouch->setChecked(false); + if (v & GenericSystemInfoScriptInterface::MultiTouch) + ui->systemInfoInputMultiTouch->setChecked(true); + else + ui->systemInfoInputMultiTouch->setChecked(false); + if (v & GenericSystemInfoScriptInterface::Mouse) + ui->systemInfoInputMouse->setChecked(true); + else + ui->systemInfoInputMouse->setChecked(false); +} + +void GenericSystemInfoScriptInterface::setImei(const QString &v) +{ + if (ui->systemInfoImei->text() != v) { + ui->systemInfoImei->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setImsi(const QString &v) +{ + if (ui->systemInfoImsi->text() != v) { + ui->systemInfoImsi->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setManufacturer(const QString &v) +{ + if (ui->systemInfoManufacturer->text() != v) { + ui->systemInfoManufacturer->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setModel(const QString &v) +{ + if (ui->systemInfoModel->text() != v) { + ui->systemInfoModel->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setProductName(const QString &v) +{ + if (ui->systemInfoProductName->text() != v) { + ui->systemInfoProductName->setText(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setBatteryLevel(int v) +{ + if (ui->systemInfoBatteryLevel->value() != v) { + ui->systemInfoBatteryLevel->setValue(v); + ui->emitGenericDataChanged(); + } +} + +void GenericSystemInfoScriptInterface::setDeviceLocked(bool v) +{ + if (ui->systemInfoDeviceLocked->isChecked() != v) { + ui->systemInfoDeviceLocked->setChecked(v); + ui->emitGenericDataChanged(); + } +} diff --git a/src/ui/systeminfogenericui.h b/src/ui/systeminfogenericui.h new file mode 100644 index 0000000..30013dc --- /dev/null +++ b/src/ui/systeminfogenericui.h @@ -0,0 +1,310 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SYSINFOGENERICUI_H +#define SYSINFOGENERICUI_H + +#include <remotecontrolwidget/toolbox.h> +#include <remotecontrolwidget/batterybutton.h> +#include <remotecontrolwidget/powerbutton.h> + +#include <QtCore/QObject> +#include <QtCore/QHash> + +class BatteryButton; +class PowerButton; +class QLineEdit; +class QComboBox; +class QLabel; +class QSpinBox; +class QCheckBox; + +class GenericSystemInfoUi; + +class GenericSystemInfoScriptInterface : public QObject +{ + Q_OBJECT +public: + //must mimic QSystem::Version + enum Version { + Os = 1, + QtCore, + Firmware + }; + Q_ENUMS(Version) + + //must mimic QSystem::Feature + enum Feature { + BluetoothFeature=0, + CameraFeature, + FmradioFeature, + IrFeature, + LedFeature, + MemcardFeature, + UsbFeature, + VibFeature, + WlanFeature, + SimFeature, + LocationFeature, + VideoOutFeature, + HapticsFeature + }; + Q_ENUMS(Feature) + + //must mimic QSystemDeviceInfo::BatteryStatus + enum BatteryStatus { + NoBatteryLevel = 0, + BatteryCritical, + BatteryVeryLow, + BatteryLow, + BatteryNormal + }; + Q_ENUMS(BatteryStatus) + + //must mimic QSystemDeviceInfo::PowerState + enum PowerState { + UnknownPower = 0, + BatteryPower, + WallPower, + WallPowerChargingBattery + }; + Q_ENUMS(PowerState) + + //must mimic QSystemDeviceInfo::InputMethod + enum InputMethod { + Keys = 0x0000001, + Keypad = 0x0000002, + Keyboard = 0x0000004, + SingleTouch = 0x0000008, + MultiTouch = 0x0000010, + Mouse = 0x0000020 + }; + Q_DECLARE_FLAGS(InputMethodFlags, InputMethod) + Q_ENUMS(InputMethod) + Q_FLAGS(InputMethodFlags) + + //must mimic QSystemDeviceInfo::Profile + enum Profile { + UnknownProfile = 0, + SilentProfile, + NormalProfile, + LoudProfile, + VibProfile, + OfflineProfile, + PowersaveProfile, + CustomProfile + }; + Q_ENUMS(Profile) + + //must mimic QSystemDeviceInfo::SimStatus + enum SimStatus { + SimNotAvailable = 0, + SingleSimAvailable, + DualSimAvailable, + SimLocked + }; + Q_ENUMS(SimStatus) + + explicit GenericSystemInfoScriptInterface(GenericSystemInfoUi *ui); + ~GenericSystemInfoScriptInterface(); + + QString currentLanguage() const; + QStringList availableLanguages() const; + QString currentCountryCode() const; + Q_INVOKABLE bool hasFeature(GenericSystemInfoScriptInterface::Feature f) const; + Q_INVOKABLE QString version(GenericSystemInfoScriptInterface::Version v, const QString ¶m = "") const; + int displayBrightness(int screen = 0) const; + int colorDepth(int screen = 0) const; + GenericSystemInfoScriptInterface::Profile currentProfile() const; + GenericSystemInfoScriptInterface::PowerState currentPowerState() const; + GenericSystemInfoScriptInterface::SimStatus simStatus() const; + GenericSystemInfoScriptInterface::InputMethodFlags inputMethod() const; + QString imei() const; + QString imsi() const; + QString manufacturer() const; + QString model() const; + QString productName() const; + int batteryLevel() const; + bool isDeviceLocked() const; + Q_INVOKABLE GenericSystemInfoScriptInterface::BatteryStatus batteryStatus() const; + + Q_PROPERTY(QString currentLanguage READ currentLanguage WRITE setCurrentLanguage) + Q_PROPERTY(QStringList availableLanguages READ availableLanguages WRITE setAvailableLanguages) + Q_PROPERTY(QString currentCountryCode READ currentCountryCode WRITE setCurrentCountryCode) + Q_PROPERTY(int displayBrightness READ displayBrightness WRITE setDisplayBrightness) + Q_PROPERTY(int colorDepth READ colorDepth WRITE setColorDepth) + Q_PROPERTY(Profile currentProfile READ currentProfile WRITE setCurrentProfile) + Q_PROPERTY(PowerState currentPowerState READ currentPowerState WRITE setCurrentPowerState) + Q_PROPERTY(SimStatus simStatus READ simStatus WRITE setSimStatus) + Q_PROPERTY(InputMethodFlags inputMethod READ inputMethod WRITE setInputMethod) + Q_PROPERTY(QString imei READ imei WRITE setImei) + Q_PROPERTY(QString imsi READ imsi WRITE setImsi) + Q_PROPERTY(QString manufacturer READ manufacturer WRITE setManufacturer) + Q_PROPERTY(QString model READ model WRITE setModel) + Q_PROPERTY(QString productName READ productName WRITE setProductName) + Q_PROPERTY(int batteryLevel READ batteryLevel WRITE setBatteryLevel) + Q_PROPERTY(bool deviceLocked READ isDeviceLocked WRITE setDeviceLocked) + +public slots: + void setCurrentLanguage(const QString &v); + void setCurrentCountryCode(const QString &v); + void setAvailableLanguages(const QStringList &v); + void addAvailableLanguage(const QString &v); + bool removeAvailableLanguage(const QString &v); + void removeAllAvailableLanguages(); + void setFeature(GenericSystemInfoScriptInterface::Feature f, bool enabled); + void setVersion(GenericSystemInfoScriptInterface::Version v, const QString &to); + void setDisplayBrightness(int brightness); + void setColorDepth(int depth); + void setCurrentProfile(GenericSystemInfoScriptInterface::Profile v); + void setCurrentPowerState(GenericSystemInfoScriptInterface::PowerState v); + void setSimStatus(GenericSystemInfoScriptInterface::SimStatus v); + void setInputMethod(GenericSystemInfoScriptInterface::InputMethodFlags v); + void setImei(const QString &v); + void setImsi(const QString &v); + void setManufacturer(const QString &v); + void setModel(const QString &v); + void setProductName(const QString &v); + void setBatteryLevel(int v); + void setDeviceLocked(bool v); + +private: + GenericSystemInfoUi *ui; +}; + +class GenericSystemInfoUi : public ToolBoxPage +{ + Q_OBJECT +public: + struct GenericData { + GenericData(); + + QString currentLanguage; + QStringList availableLanguages; + QString currentCountryCode; + int displayBrightness; + int colorDepth; + GenericSystemInfoScriptInterface::Profile profile; + GenericSystemInfoScriptInterface::PowerState currentPowerState; + GenericSystemInfoScriptInterface::SimStatus simStatus; + GenericSystemInfoScriptInterface::InputMethodFlags inputFlags; + QString imei; + QString imsi; + QString manufacturer; + QString model; + QString productName; + int batteryLevel; + bool deviceLocked; + + QVector<bool> features; + QVector<QString> versions; + }; + explicit GenericSystemInfoUi(QWidget *parent = 0); + virtual ~GenericSystemInfoUi(); + + GenericSystemInfoScriptInterface *scriptInterface(); + + GenericData genericData() const; + +public slots: + void setGenericData(const GenericSystemInfoUi::GenericData &data); + void setDisplayedGenericData(const GenericSystemInfoUi::GenericData &data); + +signals: + void genericDataChanged(const GenericSystemInfoUi::GenericData &data) const; + + // since the quick access button enums differ from the enums here, + // we need these translator slots/signals +public slots: + void setCurrentBatteryLevel(BatteryButton::BatteryLevel); + void setCurrentPowerState(PowerButton::PowerState); +signals: + void currentBatteryLevelChanged(BatteryButton::BatteryLevel) const; + void currentPowerStateChanged(PowerButton::PowerState) const; +private slots: + void emitButtonSignalsOnChange(); + +private slots: + void emitGenericDataChanged(); + +private slots: + void sysinfoAddAvailableLanguage(); + void sysinfoRemoveAvailableLanguage(); + void sysinfoToggleFeature(); + void sysinfoChangeVersion(); + void sysinfoDisplayVersion(); + void sysinfoDisplayFeature(); + void sysinfoSetAvailableLanguages(const QStringList &list); + + void sysinfoUpdateBatteryStatus(int level); + +private: + void initializeGeneric(); + + void initializeGenericOptions(); + void initializeDeviceOptions(); + + +private: + GenericData data; + QLineEdit *systemInfoLanguage; + QLineEdit *systemInfoCountryCode; + QComboBox *systemInfoAvailableLanguages; + QComboBox *systemInfoFeatures; + QLabel *systemInfoFeatureEnabled; + QComboBox *systemInfoVersions; + QLabel *systemInfoVersionString; + QSpinBox *systemInfoBatteryLevel; + QLabel *systemInfoBatteryStatus; + QComboBox *systemInfoPowerState; + QComboBox *systemInfoProfile; + QComboBox *systemInfoSimStatus; + QLineEdit *systemInfoImei; + QLineEdit *systemInfoImsi; + QCheckBox *systemInfoInputKeys; + QCheckBox *systemInfoInputKeypad; + QCheckBox *systemInfoInputKeyboard; + QCheckBox *systemInfoInputSingleTouch; + QCheckBox *systemInfoInputMultiTouch; + QCheckBox *systemInfoInputMouse; + QCheckBox *systemInfoDeviceLocked; + QLineEdit *systemInfoManufacturer; + QLineEdit *systemInfoModel; + QLineEdit *systemInfoProductName; + QSpinBox *systemInfoColorDepth; + QSpinBox *systemInfoBrightness; + + QVector<bool> mFeatures; + QVector<QString> mVersions; + + GenericSystemInfoScriptInterface *mScriptInterface; + friend class GenericSystemInfoScriptInterface; +}; + +#endif // SYSINFOGENERICUI_H diff --git a/src/ui/systeminfonetworkui.cpp b/src/ui/systeminfonetworkui.cpp new file mode 100644 index 0000000..d83d4a9 --- /dev/null +++ b/src/ui/systeminfonetworkui.cpp @@ -0,0 +1,482 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "systeminfonetworkui.h" + +#include <QtCore/QMetaEnum> +#include <QtGui/QPushButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QComboBox> +#include <QtGui/QCheckBox> +#include <QtGui/QLabel> +#include <QtGui/QSpinBox> +#include <QtGui/QFormLayout> +#include <QtGui/QGroupBox> +#include <QtGui/QInputDialog> + +void NetworkSystemInfoUi::initializeNetwork() +{ + QStringList tags; + QList<OptionsItem *> optionsList; + + networkCellId = new QSpinBox(); + networkCellId->setRange(0, 999999999); + connect(networkCellId, SIGNAL(editingFinished()), this, SLOT(emitNetworkDataChange())); + OptionsItem *item = new OptionsItem(tr("Cell ID"), networkCellId); + item->setTags(tags); + optionsList << item; + + networkLocationAreaCode = new QSpinBox(); + networkLocationAreaCode->setRange(0, 999999999); + connect(networkLocationAreaCode, SIGNAL(editingFinished()), this, SLOT(emitNetworkDataChange())); + item = new OptionsItem(tr("Location area code"), networkLocationAreaCode); + item->setTags(tags); + optionsList << item; + + networkMobileCountryCode = new QLineEdit(); + networkMobileCountryCode->setInputMask("999"); + networkMobileCountryCode->setValidator(new QRegExpValidator(QRegExp("\\d{3}"), networkMobileCountryCode)); + item = new OptionsItem(tr("Mobile country code"), networkMobileCountryCode); + connect(networkMobileCountryCode, SIGNAL(editingFinished()), this, SLOT(emitNetworkDataChange())); + item->setTags(tags); + optionsList << item; + + networkMobileNetworkCode = new QLineEdit(); + QRegExp rx("\\d*"); + networkMobileNetworkCode->setValidator(new QRegExpValidator(rx, 0)); + + connect(networkMobileNetworkCode, SIGNAL(editingFinished()), this, SLOT(emitNetworkDataChange())); + item = new OptionsItem(tr("Mobile network code"), networkMobileNetworkCode); + item->setTags(tags); + optionsList << item; + + networkHomeCountryCode = new QLineEdit(); + networkHomeCountryCode->setInputMask("+990"); + networkHomeCountryCode->setValidator(new QRegExpValidator(QRegExp("\\+\\d\\d[\\d\\s]?"), networkHomeCountryCode)); + connect(networkHomeCountryCode, SIGNAL(editingFinished()), this, SLOT(emitNetworkDataChange())); + item = new OptionsItem(tr("Home country code"), networkHomeCountryCode); + item->setTags(tags); + optionsList << item; + + networkHomeNetworkCode = new QLineEdit(); + networkHomeNetworkCode->setValidator(new QRegExpValidator(rx, 0)); + connect(networkHomeNetworkCode, SIGNAL(editingFinished()), this, SLOT(emitNetworkDataChange())); + item = new OptionsItem(tr("Home network code"), networkHomeNetworkCode); + item->setTags(tags); + optionsList << item; + + networkCurrentMode = new QComboBox(); + connect(networkCurrentMode, SIGNAL(activated(int)), this, SLOT(emitNetworkDataChange())); + item = new OptionsItem(tr("Currently active mode"), networkCurrentMode); + optionsList << item; + + networkModes = new QComboBox(); + networkName = new QLineEdit(); + networkStatus = new QComboBox(); + networkMacAddress = new QLineEdit(); + networkMacAddress->setInputMask("HH:HH:HH:HH:HH:HH"); + networkMacAddress->setValidator(new QRegExpValidator(QRegExp("(\\S\\S:){5}\\S\\S"), networkMacAddress)); + networkSignalStrength = new QSpinBox(); + networkSignalStrength->setRange(-1, 100); + networkSignalStrength->setValue(-1); + QFormLayout *fLayout = new QFormLayout(); + fLayout->addRow(tr("Name"), networkName); + fLayout->addRow(tr("Status"), networkStatus); + fLayout->addRow(tr("MAC address"), networkMacAddress); + fLayout->addRow(tr("Signal Strength"), networkSignalStrength); + QGroupBox *networkModeProperties = new QGroupBox(tr("Properties")); + networkModeProperties->setLayout(fLayout); + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->addWidget(new QLabel(tr("Edit properties of"))); + hLayout->addWidget(networkModes); + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->addLayout(hLayout); + vLayout->addWidget(networkModeProperties); + networkModeProperties = new QGroupBox(); + networkModeProperties->setLayout(vLayout); + QPushButton *toggleNetworkSettingsVisible = new QPushButton(tr("Show")); + connect(networkModes, SIGNAL(activated(int)), this, SLOT(showNetworkMode())); + connect(networkName, SIGNAL(editingFinished()), this, SLOT(editNetworkMode())); + connect(networkStatus, SIGNAL(activated(int)), this, SLOT(editNetworkMode())); + connect(networkMacAddress, SIGNAL(editingFinished()), this, SLOT(editNetworkMode())); + connect(networkSignalStrength, SIGNAL(editingFinished()), this, SLOT(editNetworkMode())); + item = new OptionsItem("Network mode properties", toggleNetworkSettingsVisible); + QStringList networkModeTags = tags; + networkModeTags << tr("name") << tr("status") << tr("mac") << tr("address") << tr("mode") << tr("signal") << tr("strength"); + item->setTags(networkModeTags); + OptionsItem *advancedItem = new OptionsItem("", networkModeProperties, true); + item->setAdvancedPage(advancedItem); + optionsList << item; + + initializeNetworkOptions(); + + setTitle(tr("Network")); + setOptions(optionsList); +} + +void NetworkSystemInfoUi::initializeNetworkOptions() +{ + networkStatus->clear(); + // depends on order + networkStatus->addItem(tr("Undefined")); + networkStatus->addItem(tr("No Network Available")); + networkStatus->addItem(tr("Emergency Only")); + networkStatus->addItem(tr("Searching")); + networkStatus->addItem(tr("Busy")); + networkStatus->addItem(tr("Connected")); + networkStatus->addItem(tr("Home Network")); + networkStatus->addItem(tr("Denied")); + networkStatus->addItem(tr("Roaming")); + + networkCurrentMode->clear(); + // depends on order + networkCurrentMode->addItem(tr("Unknown Mode"), NetworkSystemInfoScriptInterface::UnknownMode); + networkCurrentMode->addItem(tr("GSM Mode"), NetworkSystemInfoScriptInterface::GsmMode); + networkCurrentMode->addItem(tr("CDMA Mode"), NetworkSystemInfoScriptInterface::CdmaMode); + networkCurrentMode->addItem(tr("W-CDMA Mode"), NetworkSystemInfoScriptInterface::WcdmaMode); + networkCurrentMode->addItem(tr("WLAN Mode"), NetworkSystemInfoScriptInterface::WlanMode); + networkCurrentMode->addItem(tr("Ethernet Mode"), NetworkSystemInfoScriptInterface::EthernetMode); + networkCurrentMode->addItem(tr("Bluetooth Mode"), NetworkSystemInfoScriptInterface::BluetoothMode); + networkCurrentMode->addItem(tr("WiMAX Mode"), NetworkSystemInfoScriptInterface::WimaxMode); + + networkModes->clear(); + // depends on order + networkModes->addItem(tr("Unknown Mode"), NetworkSystemInfoScriptInterface::UnknownMode); + networkModes->addItem(tr("GSM Mode"), NetworkSystemInfoScriptInterface::GsmMode); + networkModes->addItem(tr("CDMA Mode"), NetworkSystemInfoScriptInterface::CdmaMode); + networkModes->addItem(tr("W-CDMA Mode"), NetworkSystemInfoScriptInterface::WcdmaMode); + networkModes->addItem(tr("WLAN Mode"), NetworkSystemInfoScriptInterface::WlanMode); + networkModes->addItem(tr("Ethernet Mode"), NetworkSystemInfoScriptInterface::EthernetMode); + networkModes->addItem(tr("Bluetooth Mode"), NetworkSystemInfoScriptInterface::BluetoothMode); + networkModes->addItem(tr("WiMAX Mode"), NetworkSystemInfoScriptInterface::WimaxMode); + + networkModeInfo.resize(8); + showNetworkMode(); +} + +NetworkSystemInfoUi::NetworkData::NetworkData() + : networkInfo(8) +{ +} + + +NetworkSystemInfoUi::NetworkSystemInfoUi(QWidget *parent) + : ToolBoxPage(parent) +{ + mScriptInterface = new NetworkSystemInfoScriptInterface(this); + initializeNetwork(); + + // update displayed values when underlying data changes + connect(this, SIGNAL(networkDataChanged(NetworkSystemInfoUi::NetworkData)), SLOT(showNetworkMode())); + + // button translators + connect(this, SIGNAL(networkDataChanged(NetworkSystemInfoUi::NetworkData)), SLOT(emitButtonSignalsOnChange())); +} + +NetworkSystemInfoUi::~NetworkSystemInfoUi() +{ +} + +NetworkSystemInfoScriptInterface *NetworkSystemInfoUi::scriptInterface() +{ + return mScriptInterface; +} + +void NetworkSystemInfoUi::showNetworkMode() +{ + int index = networkModes->itemData(networkModes->currentIndex()).toInt(); + const NetworkData::ModeInfo &info = networkModeInfo.at(index); + networkName->setText(info.name); + networkMacAddress->setText(info.macAddress); + networkSignalStrength->setValue(info.signalStrength); + networkStatus->setCurrentIndex(static_cast<int>(info.status)); +} + +void NetworkSystemInfoUi::editNetworkMode() +{ + int index = networkModes->currentIndex(); + networkModeInfo[index].name = networkName->text(); + networkModeInfo[index].macAddress = networkMacAddress->text(); + networkModeInfo[index].signalStrength = networkSignalStrength->value(); + networkModeInfo[index].status = static_cast<NetworkSystemInfoScriptInterface::NetworkStatus>(networkStatus->currentIndex()); + + emitNetworkDataChange(); +} + +void NetworkSystemInfoUi::emitNetworkDataChange() +{ + emit networkDataChanged(networkData()); +} + +NetworkSystemInfoUi::NetworkData NetworkSystemInfoUi::networkData() const +{ + NetworkData d; + d.cellId = mScriptInterface->cellId(); + d.locationAreaCode = mScriptInterface->locationAreaCode(); + d.currentMobileCountryCode = mScriptInterface->currentMobileCountryCode(); + d.currentMobileNetworkCode = mScriptInterface->currentMobileNetworkCode(); + d.homeMobileCountryCode = mScriptInterface->homeMobileCountryCode(); + d.homeMobileNetworkCode = mScriptInterface->homeMobileNetworkCode(); + d.currentMode = mScriptInterface->currentMode(); + d.networkInfo = networkModeInfo; + return d; +} + +void NetworkSystemInfoUi::setNetworkData(const NetworkSystemInfoUi::NetworkData &data) +{ + setDisplayedNetworkData(data); + emit networkDataChanged(data); +} + +void NetworkSystemInfoUi::setDisplayedNetworkData(const NetworkSystemInfoUi::NetworkData &data) +{ + networkCellId->setValue(data.cellId); + networkLocationAreaCode->setValue(data.locationAreaCode); + networkMobileCountryCode->setText(data.currentMobileCountryCode); + networkMobileNetworkCode->setText(data.currentMobileNetworkCode); + networkHomeCountryCode->setText(data.homeMobileCountryCode); + networkHomeNetworkCode->setText(data.homeMobileNetworkCode); + networkCurrentMode->setCurrentIndex(static_cast<int>(data.currentMode)); + networkModeInfo = data.networkInfo; + showNetworkMode(); +} + +void NetworkSystemInfoUi::emitButtonSignalsOnChange() +{ + NetworkSystemInfoScriptInterface::NetworkMode currentMode = mScriptInterface->currentMode(); + emit currentNetworkModeChanged(static_cast<NetworkModeButton::NetworkMode>(currentMode)); + + int strength = mScriptInterface->networkSignalStrength(currentMode); + + SignalStrengthButton::SignalStrength s; + if (strength == 0) { + s = SignalStrengthButton::NoSignal; + } else if (strength <= 20) { + s = SignalStrengthButton::SignalVeryLow; + } else if (strength <= 40) { + s = SignalStrengthButton::SignalLow; + } else { + s = SignalStrengthButton::SignalNormal; + } + emit currentNetworkSignalStrengthChanged(s); +} + +void NetworkSystemInfoUi::setCurrentNetworkMode(NetworkModeButton::NetworkMode m) +{ + mScriptInterface->setCurrentMode(static_cast<NetworkSystemInfoScriptInterface::NetworkMode>(m)); +} + +void NetworkSystemInfoUi::setCurrentNetworkSignalStrength(SignalStrengthButton::SignalStrength s) +{ + NetworkSystemInfoScriptInterface::NetworkMode mode = mScriptInterface->currentMode(); + + switch (s) { + case SignalStrengthButton::NoSignal: + mScriptInterface->setNetworkSignalStrength(mode, 0); + break; + case SignalStrengthButton::SignalVeryLow: + mScriptInterface->setNetworkSignalStrength(mode, 20); + break; + case SignalStrengthButton::SignalLow: + mScriptInterface->setNetworkSignalStrength(mode, 40); + break; + case SignalStrengthButton::SignalNormal: + mScriptInterface->setNetworkSignalStrength(mode, 100); + break; + } +} + + +/*! + \class NetworkSystemInfoScriptInterface + \brief Exposed as sysinfo.network. +*/ + +NetworkSystemInfoScriptInterface::NetworkSystemInfoScriptInterface(NetworkSystemInfoUi *ui) + : QObject(ui) + , ui(ui) +{ + int enumIndex = metaObject()->indexOfEnumerator("NetworkStatus"); + QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); + + enumIndex = metaObject()->indexOfEnumerator("NetworkMode"); + metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); +} + +NetworkSystemInfoScriptInterface::~NetworkSystemInfoScriptInterface() +{ +} + +int NetworkSystemInfoScriptInterface::cellId() const +{ + return ui->networkCellId->value(); +} + +void NetworkSystemInfoScriptInterface::setCellId(int id) +{ + if (id != cellId()) { + ui->networkCellId->setValue(id); + ui->emitNetworkDataChange(); + } +} + +int NetworkSystemInfoScriptInterface::locationAreaCode() const +{ + return ui->networkLocationAreaCode->value(); +} + +void NetworkSystemInfoScriptInterface::setLocationAreaCode(int code) +{ + if (code != locationAreaCode()) { + ui->networkLocationAreaCode->setValue(code); + ui->emitNetworkDataChange(); + } +} + +QString NetworkSystemInfoScriptInterface::currentMobileCountryCode() const +{ + return ui->networkMobileCountryCode->text(); +} + +QString NetworkSystemInfoScriptInterface::currentMobileNetworkCode() const +{ + return ui->networkMobileNetworkCode->text(); +} + +QString NetworkSystemInfoScriptInterface::homeMobileCountryCode() const +{ + return ui->networkHomeCountryCode->text(); +} + +QString NetworkSystemInfoScriptInterface::homeMobileNetworkCode() const +{ + return ui->networkHomeNetworkCode->text(); +} + +void NetworkSystemInfoScriptInterface::setCurrentMobileCountryCode(const QString &code) +{ + if (code != currentMobileCountryCode()) { + ui->networkMobileCountryCode->setText(code); + ui->emitNetworkDataChange(); + } +} + +void NetworkSystemInfoScriptInterface::setCurrentMobileNetworkCode(const QString &code) +{ + if (code != currentMobileNetworkCode()) { + ui->networkMobileNetworkCode->setText(code); + ui->emitNetworkDataChange(); + } +} + +void NetworkSystemInfoScriptInterface::setHomeMobileCountryCode(const QString &code) +{ + if (code != homeMobileCountryCode()) { + ui->networkHomeCountryCode->setText(code); + ui->emitNetworkDataChange(); + } +} + +void NetworkSystemInfoScriptInterface::setHomeMobileNetworkCode(const QString &code) +{ + if (code != homeMobileNetworkCode()) { + ui->networkHomeNetworkCode->setText(code); + ui->emitNetworkDataChange(); + } +} + +NetworkSystemInfoScriptInterface::NetworkMode NetworkSystemInfoScriptInterface::currentMode() const +{ + return static_cast<NetworkMode>(ui->networkCurrentMode->currentIndex()); +} + +void NetworkSystemInfoScriptInterface::setCurrentMode(NetworkSystemInfoScriptInterface::NetworkMode m) +{ + if (m != currentMode()) { + ui->networkCurrentMode->setCurrentIndex(static_cast<int>(m)); + ui->emitNetworkDataChange(); + } +} + +QString NetworkSystemInfoScriptInterface::networkName(NetworkMode m) const +{ + return ui->networkModeInfo.at(static_cast<int>(m)).name; +} + +void NetworkSystemInfoScriptInterface::setNetworkName(NetworkMode m, const QString &name) +{ + if (name != networkName(m)) { + ui->networkModeInfo[static_cast<int>(m)].name = name; + ui->emitNetworkDataChange(); + } +} + +QString NetworkSystemInfoScriptInterface::macAddress(NetworkMode m) const +{ + return ui->networkModeInfo.at(static_cast<int>(m)).macAddress; +} + +void NetworkSystemInfoScriptInterface::setNetworkMacAddress(NetworkMode m, const QString &mac) +{ + if (mac != macAddress(m)) { + ui->networkModeInfo[static_cast<int>(m)].macAddress = mac; + ui->emitNetworkDataChange(); + } +} + +qint32 NetworkSystemInfoScriptInterface::networkSignalStrength(NetworkMode m) const +{ + return ui->networkModeInfo.at(static_cast<int>(m)).signalStrength; +} + +void NetworkSystemInfoScriptInterface::setNetworkSignalStrength(NetworkMode m, qint32 strength) +{ + if (strength != networkSignalStrength(m)) { + ui->networkModeInfo[static_cast<int>(m)].signalStrength = strength; + ui->emitNetworkDataChange(); + } +} + +NetworkSystemInfoScriptInterface::NetworkStatus NetworkSystemInfoScriptInterface::networkStatus(NetworkMode m) const +{ + return ui->networkModeInfo.at(static_cast<int>(m)).status; +} + +void NetworkSystemInfoScriptInterface::setNetworkStatus(NetworkMode m, NetworkSystemInfoScriptInterface::NetworkStatus status) +{ + if (status != networkStatus(m)) { + ui->networkModeInfo[static_cast<int>(m)].status = status; + ui->emitNetworkDataChange(); + } +} diff --git a/src/ui/systeminfonetworkui.h b/src/ui/systeminfonetworkui.h new file mode 100644 index 0000000..8fdbab5 --- /dev/null +++ b/src/ui/systeminfonetworkui.h @@ -0,0 +1,208 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SYSINFONETWORKUI_H +#define SYSINFONETWORKUI_H + +#include <remotecontrolwidget/toolbox.h> +#include <remotecontrolwidget/networkmodebutton.h> +#include <remotecontrolwidget/signalstrengthbutton.h> + +#include <QtCore/QObject> + +class ConfigurationWidget; +class NetworkModeButton; +class SignalStrengthButton; +class QLineEdit; +class QComboBox; +class QLabel; +class QSpinBox; +class QCheckBox; + +class NetworkSystemInfoUi; + +class NetworkSystemInfoScriptInterface : public QObject +{ + Q_OBJECT +public: + // must mimic QSystemNetworkInfo::NetworkStatus + enum NetworkStatus { + UndefinedStatus = 0, + NoNetworkAvailable, + EmergencyOnly, + Searching, + Busy, + Connected, + HomeNetwork, + Denied, + Roaming + }; + Q_ENUMS(NetworkStatus) + + // must mimic QSystemNetworkInfo::NetworkMode + enum NetworkMode { + UnknownMode=0, + GsmMode, + CdmaMode, + WcdmaMode, + WlanMode, + EthernetMode, + BluetoothMode, + WimaxMode + }; + Q_ENUMS(NetworkMode) + + explicit NetworkSystemInfoScriptInterface(NetworkSystemInfoUi *ui); + virtual ~NetworkSystemInfoScriptInterface(); + + int cellId() const; + int locationAreaCode() const; + QString currentMobileCountryCode() const; + QString currentMobileNetworkCode() const; + QString homeMobileCountryCode() const; + QString homeMobileNetworkCode() const; + NetworkMode currentMode() const; + + Q_PROPERTY(int cellId READ cellId WRITE setCellId) + Q_PROPERTY(int locationAreaCode READ locationAreaCode WRITE setLocationAreaCode) + Q_PROPERTY(QString currentMobileCountryCode READ currentMobileCountryCode WRITE setCurrentMobileCountryCode) + Q_PROPERTY(QString currentMobileNetworkCode READ currentMobileNetworkCode WRITE setCurrentMobileNetworkCode) + Q_PROPERTY(QString homeMobileCountryCode READ homeMobileCountryCode WRITE setHomeMobileCountryCode) + Q_PROPERTY(QString homeMobileNetworkCode READ homeMobileNetworkCode WRITE setHomeMobileNetworkCode) + Q_PROPERTY(NetworkMode currentMode READ currentMode WRITE setCurrentMode) + + Q_INVOKABLE QString networkName(NetworkMode m) const; + Q_INVOKABLE QString macAddress(NetworkMode m) const; + Q_INVOKABLE qint32 networkSignalStrength(NetworkMode m) const; + Q_INVOKABLE NetworkStatus networkStatus(NetworkMode m) const; + +public slots: + void setCellId(int id); + void setLocationAreaCode(int code); + void setCurrentMobileCountryCode(const QString &code); + void setCurrentMobileNetworkCode(const QString &code); + void setHomeMobileCountryCode(const QString &code); + void setHomeMobileNetworkCode(const QString &code); + void setCurrentMode(NetworkSystemInfoScriptInterface::NetworkMode m); + + void setNetworkName(NetworkSystemInfoScriptInterface::NetworkMode m, const QString &name); + void setNetworkMacAddress(NetworkSystemInfoScriptInterface::NetworkMode m, const QString &mac); + void setNetworkSignalStrength(NetworkSystemInfoScriptInterface::NetworkMode m, qint32 strength); + void setNetworkStatus(NetworkSystemInfoScriptInterface::NetworkMode m, NetworkSystemInfoScriptInterface::NetworkStatus status); + +private: + NetworkSystemInfoUi *ui; +}; + +class NetworkSystemInfoUi : public ToolBoxPage +{ + Q_OBJECT +public: + struct NetworkData + { + NetworkData(); + + struct ModeInfo + { + NetworkSystemInfoScriptInterface::NetworkStatus status; + QString name; + QString macAddress; + qint32 signalStrength; + //QNetworkInterface interface; + }; + + QVector<ModeInfo> networkInfo; + + int cellId; + int locationAreaCode; + + QString currentMobileCountryCode; + QString currentMobileNetworkCode; + QString homeMobileCountryCode; + QString homeMobileNetworkCode; + NetworkSystemInfoScriptInterface::NetworkMode currentMode; + }; + + explicit NetworkSystemInfoUi(QWidget *parent = 0); + virtual ~NetworkSystemInfoUi(); + + NetworkSystemInfoScriptInterface *scriptInterface(); + + NetworkData networkData() const; + +public slots: + void setNetworkData(const NetworkSystemInfoUi::NetworkData &data); + void setDisplayedNetworkData(const NetworkSystemInfoUi::NetworkData &data); + +signals: + void networkDataChanged(const NetworkSystemInfoUi::NetworkData &data) const; + + +// since the quick access button enums differ from the enums here, +// we need these translator slots/signals +public slots: + void setCurrentNetworkMode(NetworkModeButton::NetworkMode); + void setCurrentNetworkSignalStrength(SignalStrengthButton::SignalStrength); +signals: + void currentNetworkModeChanged(NetworkModeButton::NetworkMode) const; + void currentNetworkSignalStrengthChanged(SignalStrengthButton::SignalStrength) const; +private slots: + void emitButtonSignalsOnChange(); + + +private slots: + void emitNetworkDataChange(); + void showNetworkMode(); + void editNetworkMode(); + +private: + void initializeNetwork(); + void initializeNetworkOptions(); + +private: + QSpinBox *networkCellId; + QSpinBox *networkLocationAreaCode; + QLineEdit* networkMobileCountryCode; + QLineEdit* networkMobileNetworkCode; + QLineEdit* networkHomeCountryCode; + QLineEdit* networkHomeNetworkCode; + QComboBox *networkCurrentMode; + QComboBox *networkModes; + QLineEdit *networkName; + QComboBox *networkStatus; + QLineEdit *networkMacAddress; + QSpinBox * networkSignalStrength; + + QVector<NetworkData::ModeInfo> networkModeInfo; + + NetworkSystemInfoScriptInterface *mScriptInterface; + friend class NetworkSystemInfoScriptInterface; +}; + +#endif // SYSINFONETWORKUI_H diff --git a/src/ui/systeminfostorageui.cpp b/src/ui/systeminfostorageui.cpp new file mode 100644 index 0000000..e0fcc3a --- /dev/null +++ b/src/ui/systeminfostorageui.cpp @@ -0,0 +1,387 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "systeminfostorageui.h" + +#include <QtCore/QMetaEnum> +#include <QtGui/QPushButton> +#include <QtGui/QBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QComboBox> +#include <QtGui/QCheckBox> +#include <QtGui/QLabel> +#include <QtGui/QSpinBox> +#include <QtGui/QFormLayout> +#include <QtGui/QGroupBox> +#include <QtGui/QInputDialog> + +void StorageSystemInfoUi::initializeStorage() +{ + QStringList tags; + QList<OptionsItem *> optionsList; + tags << tr("drives") << tr("memory") << tr("storage"); + + systemInfoDrives = new QComboBox(); + QPushButton *systemInfoChangeDriveName = new QPushButton(tr("Change Name")); + QPushButton *systemInfoRemoveDrive = new QPushButton(tr("Remove")); + QPushButton *systemInfoAddDrive = new QPushButton(tr("Add")); + QHBoxLayout *hLayout = new QHBoxLayout(); + hLayout->addWidget(systemInfoChangeDriveName); + hLayout->addWidget(systemInfoRemoveDrive); + hLayout->addWidget(systemInfoAddDrive); + QVBoxLayout *vLayout = new QVBoxLayout(); + vLayout->addWidget(systemInfoDrives); + vLayout->addLayout(hLayout); + systemInfoDriveType = new QComboBox(); + systemInfoDriveTotalSpace = new QLineEdit(); + QRegExp rx("\\d*"); + systemInfoDriveTotalSpace->setValidator(new QRegExpValidator(rx, this)); + systemInfoDriveAvailableSpace = new QLineEdit(); + systemInfoDriveAvailableSpace->setValidator(new QRegExpValidator(rx, this)); + QFormLayout *driveLayout = new QFormLayout(); + driveLayout->addRow(tr("Type"), systemInfoDriveType); + driveLayout->addRow(tr("Total space"), systemInfoDriveTotalSpace); + driveLayout->addRow(tr("Available space"), systemInfoDriveAvailableSpace); + QGroupBox *drivePropertyGroupBox = new QGroupBox(tr("Storage Properties")); + drivePropertyGroupBox->setLayout(driveLayout); + vLayout->addWidget(drivePropertyGroupBox); + QWidget *drives = new QWidget(); + drives->setLayout(vLayout); + connect(systemInfoDrives, SIGNAL(activated(int)), SLOT(showDriveInfo())); + connect(systemInfoAddDrive, SIGNAL(clicked()), SLOT(addDriveClicked())); + connect(systemInfoRemoveDrive, SIGNAL(clicked()), SLOT(removeDriveClicked())); + connect(systemInfoChangeDriveName, SIGNAL(clicked()), SLOT(renameDriveClicked())); + connect(systemInfoDriveType, SIGNAL(activated(int)), SLOT(editDriveInfo())); + connect(systemInfoDriveTotalSpace, SIGNAL(editingFinished()), SLOT(editDriveInfo())); + connect(systemInfoDriveAvailableSpace, SIGNAL(editingFinished()), SLOT(editDriveInfo())); + OptionsItem *item = new OptionsItem("", drives, true); + QStringList drivesTags = tags; + drivesTags << tr("total") << tr("available") << tr("space"); + item->setTags(drivesTags); + optionsList << item; + + initializeStorageOptions(); + + setTitle(tr("Storage")); + setOptions(optionsList); +} + +void StorageSystemInfoUi::initializeStorageOptions() +{ + systemInfoDriveType->clear(); + QStringList driveTypes; + // depends on order of items + driveTypes.append(tr("No Drive")); + driveTypes.append(tr("Internal Drive")); + driveTypes.append(tr("Removable Drive")); + driveTypes.append(tr("Remote Drive")); + driveTypes.append(tr("CD-ROM Drive")); + systemInfoDriveType->addItems(driveTypes); +} + +StorageSystemInfoUi::StorageSystemInfoUi(QWidget *parent) + : ToolBoxPage(parent) +{ + mScriptInterface = new StorageSystemInfoScriptInterface(this); + + initializeStorage(); + + // when the data changes, update the display + connect(this, SIGNAL(storageDataChanged(StorageSystemInfoUi::StorageData)), + SLOT(showDriveInfo())); +} + +StorageSystemInfoScriptInterface *StorageSystemInfoUi::scriptInterface() +{ + return mScriptInterface; +} + +StorageSystemInfoUi::StorageData StorageSystemInfoUi::storageData() const +{ + return mData; +} + +void StorageSystemInfoUi::setStorageData(const StorageSystemInfoUi::StorageData &data) +{ + setDisplayedStorageData(data); + emit storageDataChanged(data); +} + +void StorageSystemInfoUi::setDisplayedStorageData(const StorageSystemInfoUi::StorageData &data) +{ + mData = data; + updateDrivesList(); +} + +void StorageSystemInfoUi::emitStorageDataChange() +{ + emit storageDataChanged(storageData()); +} + +void StorageSystemInfoUi::showDriveInfo() +{ + bool editingEnabled = systemInfoDrives->count() != 0; + systemInfoDriveType->setEnabled(editingEnabled); + systemInfoDriveAvailableSpace->setEnabled(editingEnabled); + systemInfoDriveTotalSpace->setEnabled(editingEnabled); + + if (!editingEnabled) + return; + + const QString curDrive = systemInfoDrives->currentText(); + systemInfoDriveType->setCurrentIndex(static_cast<int>(mScriptInterface->typeForDrive(curDrive))); + systemInfoDriveAvailableSpace->setText(QString::number(mScriptInterface->availableDiskSpace(curDrive))); + systemInfoDriveTotalSpace->setText(QString::number(mScriptInterface->totalDiskSpace(curDrive))); +} + +void StorageSystemInfoUi::editDriveInfo() +{ + if (systemInfoDrives->count() == 0) + return; + + const QString curDrive = systemInfoDrives->currentText(); + StorageData::DriveInfo &driveInfo = mData.drives[curDrive]; + driveInfo.type = static_cast<StorageSystemInfoScriptInterface::DriveType>(systemInfoDriveType->currentIndex()); + driveInfo.totalSpace = systemInfoDriveTotalSpace->text().toLongLong(); + driveInfo.availableSpace = systemInfoDriveAvailableSpace->text().toLongLong(); + + emitStorageDataChange(); +} + +void StorageSystemInfoUi::updateDrivesList(const QString &driveToShow) +{ + QString showDrive = driveToShow; + if (showDrive.isNull()) + showDrive = systemInfoDrives->currentText(); + + systemInfoDrives->clear(); + systemInfoDrives->addItems(mData.drives.keys()); + + if (mData.drives.contains(showDrive)) + systemInfoDrives->setCurrentIndex(mData.drives.keys().indexOf(showDrive)); + + showDriveInfo(); +} + +void StorageSystemInfoUi::renameDisplayedDrive(const QString &from, const QString &to) +{ + StorageData::DriveInfo prevDriveInfo = mData.drives.value(from); + mData.drives.remove(from); + mData.drives.insert(to, prevDriveInfo); + updateDrivesList(to); +} + +void StorageSystemInfoUi::renameDriveClicked() +{ + if (systemInfoDrives->count() == 0) + return; + + const QString oldName = systemInfoDrives->currentText(); + const QString newName = QInputDialog::getText(0, + "Change Drive Name", "Enter the new drive name:", + QLineEdit::Normal, oldName); + + if (newName.isEmpty()) + return; + + renameDisplayedDrive(oldName, newName); + emitStorageDataChange(); +} + +void StorageSystemInfoUi::addDisplayedDrive(const QString &name) +{ + StorageData::DriveInfo driveInfo; + mData.drives.insert(name, driveInfo); + updateDrivesList(name); +} + +void StorageSystemInfoUi::addDriveClicked() +{ + const QString newName = QInputDialog::getText(0, + "Add New Drive", "Enter the new drive name:"); + if (newName.isEmpty()) + return; + + addDisplayedDrive(newName); + emitStorageDataChange(); +} + +void StorageSystemInfoUi::removeDisplayedDrive(const QString &name) +{ + mData.drives.remove(name); + updateDrivesList(); +} + +void StorageSystemInfoUi::removeDriveClicked() +{ + if (systemInfoDrives->count() == 0) + return; + + removeDisplayedDrive(systemInfoDrives->currentText()); + emitStorageDataChange(); +} + + +StorageSystemInfoUi::StorageData::DriveInfo::DriveInfo() + : type(StorageSystemInfoScriptInterface::NoDrive) + , totalSpace(-1) + , availableSpace(-1) +{ +} + + +/*! + \class StorageSystemInfoScriptInterface + \brief Exposed as sysinfo.storage. +*/ + +StorageSystemInfoScriptInterface::StorageSystemInfoScriptInterface(StorageSystemInfoUi *ui) + : QObject(ui) + , ui(ui) +{ + int enumIndex = metaObject()->indexOfEnumerator("DriveType"); + QMetaEnum metaEnum = metaObject()->enumerator(enumIndex); + for (int i = 0; i < metaEnum.keyCount(); ++i) + setProperty(metaEnum.key(i), metaEnum.value(i)); +} + +StorageSystemInfoScriptInterface::~StorageSystemInfoScriptInterface() +{ +} + +QStringList StorageSystemInfoScriptInterface::logicalDrives() const +{ + return ui->mData.drives.keys(); +} + +StorageSystemInfoScriptInterface::DriveType StorageSystemInfoScriptInterface::typeForDrive(const QString &name) const +{ + if (!ui->mData.drives.contains(name)) + return NoDrive; + return ui->mData.drives.value(name).type; +} + +qint64 StorageSystemInfoScriptInterface::totalDiskSpace(const QString &name) const +{ + if (!ui->mData.drives.contains(name)) + return -1; + return ui->mData.drives.value(name).totalSpace; +} + +qint64 StorageSystemInfoScriptInterface::availableDiskSpace(const QString &name) const +{ + if (!ui->mData.drives.contains(name)) + return -1; + return ui->mData.drives.value(name).availableSpace; +} + +bool StorageSystemInfoScriptInterface::addDrive(const QString &name) +{ + if (ui->mData.drives.contains(name)) + return false; + + ui->addDisplayedDrive(name); + ui->emitStorageDataChange(); + return true; +} + +bool StorageSystemInfoScriptInterface::addDrive(const QString &name, + StorageSystemInfoScriptInterface::DriveType type, + qint64 totalSpace, qint64 availableSpace) +{ + if (ui->mData.drives.contains(name)) + return false; + + ui->addDisplayedDrive(name); + StorageSystemInfoUi::StorageData::DriveInfo &di = ui->mData.drives[name]; + di.type = type; + di.availableSpace = availableSpace; + di.totalSpace = totalSpace; + ui->emitStorageDataChange(); + return true; +} + +bool StorageSystemInfoScriptInterface::removeDrive(const QString &name) +{ + if (!ui->mData.drives.contains(name)) + return false; + + ui->removeDisplayedDrive(name); + ui->emitStorageDataChange(); + return true; +} + +bool StorageSystemInfoScriptInterface::setName(const QString &oldname, const QString &newname) +{ + if (!ui->mData.drives.contains(oldname)) + return false; + + ui->renameDisplayedDrive(oldname, newname); + ui->emitStorageDataChange(); + return true; +} + +bool StorageSystemInfoScriptInterface::setType(const QString &name, StorageSystemInfoScriptInterface::DriveType type) +{ + if (!ui->mData.drives.contains(name)) + return false; + + if (ui->mData.drives[name].type != type) + { + ui->mData.drives[name].type = type; + ui->emitStorageDataChange(); + } + return true; +} + +bool StorageSystemInfoScriptInterface::setTotalSpace(const QString &name, qint64 space) +{ + if (!ui->mData.drives.contains(name)) + return false; + + if (ui->mData.drives[name].totalSpace != space) + { + ui->mData.drives[name].totalSpace = space; + ui->emitStorageDataChange(); + } + return true; +} + +bool StorageSystemInfoScriptInterface::setAvailableSpace(const QString &name, qint64 space) +{ + if (!ui->mData.drives.contains(name)) + return false; + + if (ui->mData.drives[name].availableSpace != space) + { + ui->mData.drives[name].availableSpace = space; + ui->emitStorageDataChange(); + } + return true; +} diff --git a/src/ui/systeminfostorageui.h b/src/ui/systeminfostorageui.h new file mode 100644 index 0000000..aab3741 --- /dev/null +++ b/src/ui/systeminfostorageui.h @@ -0,0 +1,140 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SYSINFOSTORAGEUI_H +#define SYSINFOSTORAGEUI_H + +#include <remotecontrolwidget/toolbox.h> + +#include <QtCore/QObject> +#include <QtCore/QHash> + +class QLineEdit; +class QComboBox; + +class StorageSystemInfoUi; + +class StorageSystemInfoScriptInterface : public QObject +{ + Q_OBJECT +public: + // must mimic QSystemStorageInfo::DriveType + enum DriveType { + NoDrive = 0, + InternalDrive, + RemovableDrive, + RemoteDrive, + CdromDrive + }; + Q_ENUMS(DriveType) + + explicit StorageSystemInfoScriptInterface(StorageSystemInfoUi *ui); + virtual ~StorageSystemInfoScriptInterface(); + + Q_INVOKABLE QStringList logicalDrives() const; + Q_INVOKABLE DriveType typeForDrive(const QString &name) const; + Q_INVOKABLE qint64 totalDiskSpace(const QString &name) const; + Q_INVOKABLE qint64 availableDiskSpace(const QString &name) const; + +public slots: + bool addDrive(const QString &name); + bool addDrive(const QString &name, StorageSystemInfoScriptInterface::DriveType type, + qint64 totalSpace, qint64 availableSpace); + bool removeDrive(const QString &name); + bool setName(const QString &oldname, const QString &newname); + bool setType(const QString &name, StorageSystemInfoScriptInterface::DriveType type); + bool setTotalSpace(const QString &name, qint64 space); + bool setAvailableSpace(const QString &name, qint64 space); + +private: + StorageSystemInfoUi *ui; +}; + +class StorageSystemInfoUi : public ToolBoxPage +{ + Q_OBJECT +public: + struct StorageData { + struct DriveInfo + { + DriveInfo(); + + StorageSystemInfoScriptInterface::DriveType type; + qint64 totalSpace; + qint64 availableSpace; + }; + + QHash<QString, DriveInfo> drives; + }; + + explicit StorageSystemInfoUi(QWidget *parent = 0); + + StorageSystemInfoScriptInterface *scriptInterface(); + + StorageData storageData() const; + +public slots: + void setStorageData(const StorageSystemInfoUi::StorageData &data); + void setDisplayedStorageData(const StorageSystemInfoUi::StorageData &data); + +signals: + void storageDataChanged(const StorageSystemInfoUi::StorageData &data) const; + +private slots: + void emitStorageDataChange(); + void showDriveInfo(); + void editDriveInfo(); + void updateDrivesList(const QString &driveToShow = QString()); + + void addDisplayedDrive(const QString &name); + void removeDisplayedDrive(const QString &name); + void renameDisplayedDrive(const QString &from, const QString &to); + + void renameDriveClicked(); + void addDriveClicked(); + void removeDriveClicked(); + +private: + void initializeStorage(); + void initializeStorageOptions(); + + +private: + QComboBox *systemInfoDrives; + QComboBox *systemInfoDriveType; + QLineEdit *systemInfoDriveTotalSpace; + QLineEdit *systemInfoDriveAvailableSpace; + + StorageData mData; + + StorageSystemInfoScriptInterface *mScriptInterface; + friend class StorageSystemInfoScriptInterface; +}; + +#endif // SYSINFOSTORAGEUI_H diff --git a/src/ui/ui.pri b/src/ui/ui.pri new file mode 100644 index 0000000..9cb3f46 --- /dev/null +++ b/src/ui/ui.pri @@ -0,0 +1,28 @@ +INCLUDEPATH += src/ui +DEPENDPATH += src/ui +HEADERS += applicationtablewidget.h \ + mainwindow.h \ + configurationwidget.h \ + contactsui.h \ + systeminfogenericui.h \ + systeminfonetworkui.h \ + systeminfostorageui.h \ + messagingui.h \ + sensorsui.h \ + viewconfiguration.h +SOURCES += applicationtablewidget.cpp \ + mainwindow.cpp \ + configurationwidget.cpp \ + contactsui.cpp \ + systeminfogenericui.cpp \ + systeminfonetworkui.cpp \ + systeminfostorageui.cpp \ + messagingui.cpp \ + sensorsui.cpp \ + viewconfiguration.cpp +RESOURCES += menus/menus.qrc +FORMS += inspector.ui \ + viewconfiguration.ui + +RESOURCES += \ + src/ui/ui.qrc diff --git a/src/ui/ui.qrc b/src/ui/ui.qrc new file mode 100644 index 0000000..f157ed7 --- /dev/null +++ b/src/ui/ui.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/ui"> + <file>icons/hicolor/256x256/apps/Nokia-Simulator.png</file> + </qresource> +</RCC> diff --git a/src/ui/viewconfiguration.cpp b/src/ui/viewconfiguration.cpp new file mode 100644 index 0000000..c472a2c --- /dev/null +++ b/src/ui/viewconfiguration.cpp @@ -0,0 +1,175 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "viewconfiguration.h" + +#include <QtGui/QGraphicsLineItem> +#include <QtGui/QDesktopWidget> +#include <QtGui/QPainter> +#include <qmath.h> + +ViewConfiguration::ViewConfiguration(qreal correctionFactor, QWidget *parent) + : QDialog(parent) + , mCurrentCorrectionFactor(correctionFactor) + , mCurrentUnit(Centrimetre) +{ + ui.setupUi(this); + + mRulerWidget = new RulerWidget(correctionFactor, this); + ui.scrollArea->setWidget(mRulerWidget); + + qreal widthInInch = qApp->desktop()->width() / qApp->desktop()->logicalDpiX(); + qreal heightInInch = qApp->desktop()->height() / qApp->desktop()->logicalDpiY(); + mDiagonalInInch = sqrt(pow(widthInInch, 2) + pow(heightInInch, 2)); + ui.diagonalInInch->setText(QString::number(mDiagonalInInch)); + + connect(ui.horizontalSlider, SIGNAL(valueChanged(int)), SLOT(updateCorrectionFromSlider())); + connect(ui.cmRadioButton, SIGNAL(toggled(bool)), SLOT(updateUnit())); + connect(ui.inchRadioButton, SIGNAL(toggled(bool)), SLOT(updateUnit())); + connect(ui.exitButton, SIGNAL(clicked()), SLOT(close())); + connect(ui.diagonalInInch, SIGNAL(editingFinished()), SLOT(updateCorrectionFromMonitorValues())); + connect(ui.correctionFactorEdit, SIGNAL(editingFinished()), SLOT(updateCorrectionFromLineEdit())); + connect(this, SIGNAL(correctionFactorChanged(qreal)), SLOT(updateValues(qreal))); + updateValues(mCurrentCorrectionFactor); +} + +ViewConfiguration::~ViewConfiguration() +{ + +} + +void ViewConfiguration::updateValues(qreal factor) +{ + ui.horizontalSlider->setValue(factor * 100); + updateLine(); + ui.correctionFactorEdit->setText(QString::number(factor)); + ui.diagonalInInch->setText(QString::number(mDiagonalInInch / factor)); +} +void ViewConfiguration::updateLine() +{ + qreal lineWidth; + if (mCurrentUnit == Centrimetre) + lineWidth = qApp->desktop()->logicalDpiX() / 2.54 * 10 * mCurrentCorrectionFactor; + else + lineWidth = qApp->desktop()->logicalDpiX() * 4 * mCurrentCorrectionFactor; + mRulerWidget->setFixedWidth(lineWidth); + ui.scrollArea->setMinimumWidth(lineWidth); + mRulerWidget->updateCorrectionFactor(ui.horizontalSlider->value() / 100.); +} + +void ViewConfiguration::updateUnit() +{ + if (ui.cmRadioButton->isChecked()) + mCurrentUnit = Centrimetre; + else + mCurrentUnit = Inch; + mRulerWidget->updateCurrentUnit(mCurrentUnit); + updateLine(); +} + +void ViewConfiguration::updateCorrectionFromSlider() +{ + if (mCurrentCorrectionFactor != ui.horizontalSlider->value() / 100.) { + mCurrentCorrectionFactor = ui.horizontalSlider->value() / 100.; + emit correctionFactorChanged(mCurrentCorrectionFactor); + } +} + +void ViewConfiguration::updateCorrectionFromMonitorValues() +{ + mCurrentCorrectionFactor = mDiagonalInInch / ui.diagonalInInch->text().toDouble(); + if (mCurrentCorrectionFactor > 2) + mCurrentCorrectionFactor = 2; + else if (mCurrentCorrectionFactor < 0.5) + mCurrentCorrectionFactor = 0.5; + emit correctionFactorChanged(mCurrentCorrectionFactor); +} + +void ViewConfiguration::updateCorrectionFromLineEdit() +{ + qreal newValue = ui.correctionFactorEdit->text().toDouble(); + if (newValue < 0.5) + newValue = 0.5; + else if (newValue > 2) + newValue = 2; + if (mCurrentCorrectionFactor != newValue) { + mCurrentCorrectionFactor = newValue; + emit correctionFactorChanged(mCurrentCorrectionFactor); + } +} + +RulerWidget::RulerWidget(qreal correctionFactor, QWidget *parent) + : QWidget(parent) + , mCorrectionFactor(correctionFactor) + , mCurrentUnit(Centrimetre) +{ + setFixedHeight(5); +} + +void RulerWidget::updateCorrectionFactor(qreal newFactor) +{ + mCorrectionFactor = newFactor; + repaint(); +} + +void RulerWidget::updateCurrentUnit(Unit newUnit) +{ + mCurrentUnit = newUnit; + repaint(); +} + +void RulerWidget::paintEvent(QPaintEvent *e) +{ + Q_UNUSED(e); + QPalette p = QApplication::palette(); + QPainter painter(this); + painter.setPen(Qt::NoPen); + qreal oneStep = qApp->desktop()->logicalDpiX() * mCorrectionFactor;; + if (mCurrentUnit == Centrimetre) + oneStep /= 2.54; + qreal drawnWidth = 0; + bool highlight = false; + painter.setBrush(p.color(QPalette::Shadow)); + QRectF currentRect = rect(); + currentRect.setWidth(oneStep); + while ((drawnWidth + oneStep)<= rect().width()) { + painter.drawRect(currentRect); + currentRect.translate(oneStep, 0); + drawnWidth += oneStep; + if (!highlight) + painter.setBrush(p.color(QPalette::Mid)); + else + painter.setBrush(p.color(QPalette::Shadow)); + highlight ^= 1; + } + if (drawnWidth < rect().width()) { + currentRect.setWidth(rect().width() - drawnWidth); + painter.drawRect(currentRect); + } +} diff --git a/src/ui/viewconfiguration.h b/src/ui/viewconfiguration.h new file mode 100644 index 0000000..cfec72e --- /dev/null +++ b/src/ui/viewconfiguration.h @@ -0,0 +1,89 @@ +/************************************************************************** +** +** This file is part of Qt Simulator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef VIEWCONFIGURATION_H +#define VIEWCONFIGURATION_H + +#include <QDialog> +#include "ui_viewconfiguration.h" + +class QGraphicsLineItem; + +enum Unit { + Centrimetre, + Inch +}; + +class RulerWidget: public QWidget +{ + Q_OBJECT +public: + + explicit RulerWidget(qreal correctionFactor = 1, QWidget *parent = 0); + void updateCorrectionFactor(qreal newFactor); + void updateCurrentUnit(Unit newUnit); + +protected: + virtual void paintEvent(QPaintEvent *e); + +private: + qreal mCorrectionFactor; + Unit mCurrentUnit; +}; + +class ViewConfiguration : public QDialog +{ + Q_OBJECT + +public: + explicit ViewConfiguration(qreal correctionFactor = 1, QWidget *parent = 0); + ~ViewConfiguration(); + +signals: + void correctionFactorChanged(qreal factor); + +private slots: + void updateValues(qreal factor); + void updateLine(); + void updateUnit(); + + void updateCorrectionFromSlider(); + void updateCorrectionFromMonitorValues(); + void updateCorrectionFromLineEdit(); + +private: + Ui::ViewConfigurationClass ui; + + qreal mCurrentCorrectionFactor; + Unit mCurrentUnit; + qreal mDiagonalInInch; + RulerWidget *mRulerWidget; +}; + +#endif // VIEWCONFIGURATION_H diff --git a/src/ui/viewconfiguration.ui b/src/ui/viewconfiguration.ui new file mode 100644 index 0000000..c53f570 --- /dev/null +++ b/src/ui/viewconfiguration.ui @@ -0,0 +1,261 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ViewConfigurationClass</class> + <widget class="QWidget" name="ViewConfigurationClass"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>275</width> + <height>389</height> + </rect> + </property> + <property name="windowTitle"> + <string>Configuration</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <property name="sizeConstraint"> + <enum>QLayout::SetMinimumSize</enum> + </property> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Correction</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="label_4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Depending on the used operating system and configuration, it is possible that the view's "native size" setting does not reflect the real size of the device. The following two approaches can be used to correct this issue.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Monitor Values</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>The correction factor can be calculated with the help of you monitor's diagonal in inch. Just enter the correct value.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Diagonal in inches</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="diagonalInInch"/> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Manual correction</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>The line should have exactly the width given below. If it has not, use the slider to correct its length.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="unitBox" native="true"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QRadioButton" name="cmRadioButton"> + <property name="text"> + <string>10 cm</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="inchRadioButton"> + <property name="text"> + <string>4 inch</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>15</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>217</width> + <height>16</height> + </rect> + </property> + </widget> + </widget> + </item> + <item> + <widget class="QSlider" name="horizontalSlider"> + <property name="minimum"> + <number>50</number> + </property> + <property name="maximum"> + <number>200</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Correction Factor</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="correctionFactorEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="exitButton"> + <property name="text"> + <string>Exit</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources/> + <connections/> +</ui> diff --git a/stubdata/standardcontacts.vcf b/stubdata/standardcontacts.vcf new file mode 100644 index 0000000..18f08a9 --- /dev/null +++ b/stubdata/standardcontacts.vcf @@ -0,0 +1,373 @@ +BEGIN:VCARD +PHOTO:images/avatars/yilmaz_emre.png +FN:Emre Yilmaz +N:Yilmaz;Emre;;; +NAME:Emre Yilmaz +EMAIL:yilmaz@gmail.com +TEL:+447676982463 +TEL:02065792431 +ADR:;;56 Edmonton Square;Leister;;;UK +UID:1 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/wright_caroline.png +FN:Caroline Wright +N:Wright;Caroline;;; +NAME:Caroline Wright +EMAIL:wrightstuff@tiscali.co.uk +TEL:07956328190 +ADR:;;28 Dalston Road;London;;E4 8FG; +UID:2 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/taylor_steve.png +FN:Steve Taylor +N:Taylor;Steve;;; +NAME:Steve Taylor +EMAIL:stevetaylor100@hotmail.com +EMAIL:steve.taylor@orange.com +TEL:+447765238901 +ADR:;;1987 Great Western Road;Glasgow;;;UK +UID:3 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/sorenson_anita.png +FN:Anita Sorenson +N:Sorenson;Anita;;; +NAME:Anita Sorenson +EMAIL:anitasorenson@aol.com +TEL:07923409252 +ADR:;;10B Laird Street;Glasgow;;G3 6RD; +UID:4 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/shiel_becky.png +FN:Becky Shiel +N:Shiel;Becky;;; +NAME:Becky Shiel +EMAIL:beckyshiel@tate.org.uk +TEL:+44782317900 +ADR:;;89C Hackney Road;London;;E8 6NM; +UID:5 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/shakiba_nadia.png +FN:Nadia Shakiba +N:Shakiba;Nadia;;; +NAME:Nadia Shakiba +EMAIL:nadia.shakiba@ovi.com +TEL:+447906237192 +ADR:;;76 Pierce Grove;Coventry;;;UK +UID:6 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/saranouk_suzie.png +FN:Suzie Saranouk +N:Saranouk;Suzie;;; +NAME:Suzie Saranouk +EMAIL:suzie.saranouk@hotmail.com +EMAIL:suzie@tastypastries.com +TEL:02056982179 +ADR:;;69 Riverbank;Liverpool;;;UK +UID:7 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/rosencrans_claus.png +FN:Claus Rosencrans +N:Rosencrans;Claus;;; +NAME:Claus Rosencrans +EMAIL:c.rosencrans@falconindustries.com +TEL:+442076892013 +ADR:;;45 High Street;Chester;;;UK +UID:8 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/paul_lisa.png +FN:Lisa Paul +N:Paul;Lisa;;; +NAME:Lisa Paul +EMAIL:lisa.paul@ovi.com +TEL:07612984270 +ADR:;;29 Acacia Gardens;Slough;;;UK +UID:9 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/noble_emily.png +FN:Emily Noble +N:Noble;Emily;;; +NAME:Emily Noble +EMAIL:emily.noble@yahoo.co.uk +EMAIL:emily@dcs.co.uk +TEL:+44752361790 +ADR:;;12 Edinburgh Road;London;;E17 6DM; +UID:10 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/nanette_melissa.png +FN:Melissa Nanette +N:Nanette;Melissa;;; +NAME:Melissa Nanette +EMAIL:melnan@gmail.com +EMAIL:melissa@orange.com +TEL:07843729817 +ADR:;;1 Freemantle Street;Coventry;;;UK +UID:11 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/mccallum_sarah.png +FN:Sarah McCallum +N:McCallum;Sarah;;; +NAME:Sarah McCallum +EMAIL:sarahmc@tiscali.co.uk +TEL:+447923461089 +ADR:;;10B Laird Street;Glasgow;;G3 6RD; +UID:12 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/mason_mary.png +FN:Mary Mason +N:Mason;Mary;;; +NAME:Mary Mason +EMAIL:marymason@hotmail.com +TEL:020568725219 +ADR:;;12 Davis Close;Wimbledon;;;London +UID:13 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/marks_harry.png +FN:Harry Marks +N:Marks;Harry;;; +NAME:Harry Marks +EMAIL:hmarks@marksandson.co.uk +EMAIL:harrymarks@gmail.com +TEL:07902346182 +ADR:;;98 Conifer Drive;Bury St Edmunds;;;Sussex +UID:14 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/jameson_tyrone.png +FN:Tyrone Jameson +N:Jameson;Tyrone;;; +NAME:Tyrone Jameson +EMAIL:tyronej@ovi.com +TEL:+447512349825 +ADR:;;Flat 4;143 Peckam High Street;;;London +UID:15 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/jain_paresh.png +FN:Paresh Jain +N:Jain;Paresh;;; +NAME:Paresh Jain +EMAIL:pareshjain@hotmail.com +TEL:+447908252685 +ADR:;;Flat 4;143 Peckam High Street;;;London +UID:16 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/hope_darlia.png +FN:Dalia Hope +N:Hope;Dalia;;; +NAME:Dalia Hope +EMAIL:dalia@hopeandgloria.com +EMAIL:daliahope@tiscali.co.uk +TEL:+44205639021 +ADR:;;121;;;; +UID:17 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/hernandez_adriana.png +FN:Adriana Hernandez +N:Hernandez;Adriana;;; +NAME:Adriana Hernandez +EMAIL:adriana.hernandez@gmail.com +TEL:+932218200 +ADR:;;Avenida Icaria 195;08005 Barcelona;;;Spain +UID:18 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/henderson_ben.png +FN:Ben Henderson +N:Henderson;Ben;;; +NAME:Ben Henderson +EMAIL:ben@hopebikes.com +TEL:+447592020111 +ADR:;;11 Headingley Road;Leeds;;;UK +UID:19 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/hansel_justus.png +FN:Justus Hansel +N:Hansel;Justus;;; +NAME:Justus Hansel +EMAIL:justus.hansel@hotmail.com +TEL:+447628262802 +ADR:;;90 Dalbert Road;London;;W14 8GH; +UID:20 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/george_kim.png +FN:Kim George +N:George;Kim;;; +NAME:Kim George +EMAIL:kimgeorge@gmail.com +EMAIL:kim@thelittleshop.co.uk +TEL:+44780925292 +TEL:02056857291 +ADR:;;89C Hackney Road;London;;E8 6NM; +UID:21 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/ganesvoort_daatje.png +FN:Daatje Ganesvoort +N:Ganesvoort;Daatje;;; +NAME:Daatje Ganesvoort +EMAIL:d.ganesvoort@blythandhiggins.co.uk +TEL:+44786262892 +ADR:;;65 Hampstead Mansions;London;;N1 4RG; +UID:22 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/davis_tina.png +FN:Tina Davis +N:Davis;Tina;;; +NAME:Tina Davis +EMAIL:tinadavis@hotmail.com +TEL:0765271991 +ADR:;;10B Laird Street;Glasgow;;G3 6RD; +UID:23 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/dalby_elaine.png +FN:Elaine Dalby +N:Dalby;Elaine;;; +NAME:Elaine Dalby +EMAIL:elaine@dalbydj.co.uk +TEL:+447908635241 +ADR:;;89 Terrence Street;Bristol;;;UK +UID:24 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/charles_betty.png +FN:Betty Charles +N:Charles;Betty;;; +NAME:Betty Charles +EMAIL:betty.charles@blythandhiggins.co.uk +EMAIL:bcharley@yahoo.com +TEL:07954637251 +TEL:+442056572312 +ADR:;;65 Hampstead Mansions;London;;N1 4RG; +UID:25 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/chee_dan.png +FN:Dan Chee +N:Chee;Dan;;; +NAME:Dan Chee +EMAIL:danchee4@yahoo.com +TEL:079852629191 +ADR:;;143 Defoe Road;Chester;;;UK +UID:26 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/cansai_lakshya.png +FN:Lakshya Cansai +N:Cansai;Lakshya;;; +NAME:Lakshya Cansai +EMAIL:lakshya@googlemail.com +TEL:+17563828903 +ADR:;;1600 Pennsylvania Avenue;Boston;;;USA +UID:27 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/banks_jules.png +FN:Jules Banks +N:Banks;Jules;;; +NAME:Jules Banks +EMAIL:julez86@yahoo.co.uk +TEL:+447892562421 +ADR:;;187 Churchill Street;Brighton;;B13 6TF; +UID:28 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/adeyemo_fred.png +FN:Fred Adeyemo +N:Adeyemo;Fred;;; +NAME:Fred Adeyemo +EMAIL:fred.adeyemo@troll.no +TEL:+3587654321 +ADR:;;Sandakerveien 116;Oslo;;;Norway +UID:29 +VERSION:3.0 +END:VCARD + +BEGIN:VCARD +PHOTO:images/avatars/ackert_boris.png +FN:Boris Ackert +N:Ackert;Boris;;; +NAME:Boris Ackert +EMAIL:borisackert@hotmail.com +EMAIL:boris@backert.com +TEL:+4456428724 +TEL:+442087624272 +ADR:;;15 Blackhill Cresent;London;;SW11 5DF; +UID:30 +VERSION:3.0 +END:VCARD + diff --git a/stubdata/standardmessages/testmessage b/stubdata/standardmessages/testmessage new file mode 100644 index 0000000..3f05225 --- /dev/null +++ b/stubdata/standardmessages/testmessage @@ -0,0 +1,7 @@ +From: simulator@example.com
+To: user@example.com
+Subject: Test message
+Content-Type: text/plain
+Date: Thu, 4 Mar 2010 13:44:48 +0100
+
+This is a test message.
diff --git a/stubdata/standardselfcontact.vcf b/stubdata/standardselfcontact.vcf new file mode 100644 index 0000000..91e49d8 --- /dev/null +++ b/stubdata/standardselfcontact.vcf @@ -0,0 +1,10 @@ +BEGIN:VCARD +FN:Self Simulator +N:Simulator;Self;;; +NAME:Self Simulator +EMAIL:selfcontact@example.com +TEL:+44123456789 +ADR:;;56 Edmonton Square;Leister;;;UK +UID:0 +VERSION:3.0 +END:VCARD |
