summaryrefslogtreecommitdiff
authorllornkcor <llornkcor>2006-07-09 18:56:40 (UTC)
committer llornkcor <llornkcor>2006-07-09 18:56:40 (UTC)
commit36dece4760b1ac1799929221b49eb3bee98c2367 (patch) (side-by-side diff)
treea45f66d2d90bd9fbbff8e8903cd1cb9323c39f6e
parent604065c6e662cb3894acf03abadafacc3ab52913 (diff)
downloadopie-36dece4760b1ac1799929221b49eb3bee98c2367.zip
opie-36dece4760b1ac1799929221b49eb3bee98c2367.tar.gz
opie-36dece4760b1ac1799929221b49eb3bee98c2367.tar.bz2
initial commit to add video4linux camera app from qtopia 2, needs more work
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--apps/Applications/camera2.desktop26
-rw-r--r--library/backend/categories.h1
-rw-r--r--library/global.cpp49
-rw-r--r--library/global.h6
-rw-r--r--library/library.pro2
-rw-r--r--library/locationcombo.cpp295
-rw-r--r--library/locationcombo.h88
-rw-r--r--library/qlibrary_unix.cpp4
-rw-r--r--library/timestring.cpp255
-rw-r--r--library/timestring.h94
-rw-r--r--noncore/multimedia/camera2/camera2.pro27
-rw-r--r--noncore/multimedia/camera2/camerabase.cpp93
-rw-r--r--noncore/multimedia/camera2/camerabase.h47
-rw-r--r--noncore/multimedia/camera2/camerabase.ui209
-rw-r--r--noncore/multimedia/camera2/camerasettings.cpp166
-rw-r--r--noncore/multimedia/camera2/camerasettings.h59
-rw-r--r--noncore/multimedia/camera2/camerasettings.ui433
-rw-r--r--noncore/multimedia/camera2/config.in7
-rw-r--r--noncore/multimedia/camera2/image.cpp239
-rw-r--r--noncore/multimedia/camera2/image.h53
-rw-r--r--noncore/multimedia/camera2/main.cpp44
-rw-r--r--noncore/multimedia/camera2/mainwindow.cpp763
-rw-r--r--noncore/multimedia/camera2/mainwindow.h132
-rw-r--r--noncore/multimedia/camera2/opie-camera2.control10
-rw-r--r--noncore/multimedia/camera2/thumbbutton.h50
-rw-r--r--noncore/multimedia/camera2/videocaptureview.cpp599
-rw-r--r--noncore/multimedia/camera2/videocaptureview.h82
-rw-r--r--packages1
-rw-r--r--pics/camera2/Camera.pngbin0 -> 1668 bytes
-rw-r--r--pics/camera2/Camera_48.pngbin0 -> 3161 bytes
-rw-r--r--pics/camera2/Camera_48_anim.mngbin0 -> 13700 bytes
-rw-r--r--pics/camera2/settings.pngbin0 -> 745 bytes
32 files changed, 3723 insertions, 111 deletions
diff --git a/apps/Applications/camera2.desktop b/apps/Applications/camera2.desktop
new file mode 100644
index 0000000..4662080
--- a/dev/null
+++ b/apps/Applications/camera2.desktop
@@ -0,0 +1,26 @@
+[Desktop Entry]
+Exec=camera2
+File=camera2
+Icon=camera2/Camera
+Type=Application
+Name=OpieCam2
+Comment=A Camera Program
+Name[de]=Kamera2
+Comment[de]=Ein Kamera-Programm
+Name[fr]=Photo2
+Comment[fr]=Gestionnaire de photos et images
+Name[it]=Telecamera2
+Comment[it]=Programma per telecamera
+Name[pt]=Câmera2
+Comment[pt]=Uma aplicação de câmera
+Name[pt_BR]=Câmera2
+Comment[pt_BR]=Uma aplicação de câmera
+Name[sl]=OpieKamera2
+Comment[sl]=Program za kamero
+Naam[nl]=Camera2
+Comment[nl]=Een camerabesturingsprogramma
+Name[ru]=Камера2
+Comment[ru]=Программа для управления (фото)камерой
+Name[lv]=OpieCam2
+Comment[lv]=Opie Kameras Programma
+
diff --git a/library/backend/categories.h b/library/backend/categories.h
index 91c93e7..6be3bc0 100644
--- a/library/backend/categories.h
+++ b/library/backend/categories.h
@@ -1,229 +1,230 @@
/**********************************************************************
** Copyright (C) 2000 Trolltech AS. All rights reserved.
**
** This file is part of Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included
** in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
** PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef QTPALMTOP_CATEGORIES_H
#define QTPALMTOP_CATEGORIES_H
#include <qstring.h>
#include <qstringlist.h>
#include <qmap.h>
#include <qlistview.h>
#include <qarray.h>
#include "qpcglobal.h"
#include "palmtopuidgen.h"
class CategoryGroup;
+QString categoryFileName();
#if defined(QPC_TEMPLATEDLL)
// MOC_SKIP_BEGIN
template class QPC_EXPORT QMap<int, QString>;
template class QPC_EXPORT QMap<QString, int>;
template class QPC_EXPORT QMap< QString, CategoryGroup >;
// MOC_SKIP_END
#endif
class QPC_EXPORT CategoryGroup
{
friend class Categories;
public:
CategoryGroup(): mIdLabelMap(), mLabelIdMap() { }
CategoryGroup( const CategoryGroup &c ) :
mIdLabelMap( c.mIdLabelMap), mLabelIdMap( c.mLabelIdMap ) { }
void clear() { mIdLabelMap.clear(); mLabelIdMap.clear(); }
int add( const QString &label );
bool add( int uid, const QString &label );
bool remove( const QString &label );
bool remove( int uid );
bool rename( int uid, const QString &newLabel );
bool rename( const QString &oldLabel, const QString &newLabel );
bool contains(int id) const;
bool contains(const QString &label) const;
/** Returns label associated with the uid or QString::null if
* not found
*/
const QString &label(int id) const;
/** Returns the uid associated with label or 0 if not found */
int id(const QString &label) const;
/** Returns a sorted list of labels */
QStringList labels() const;
QStringList labels( const QArray<int> &catids ) const;
const QMap<int, QString> &idMap() const { return mIdLabelMap; }
private:
void insert( int uid, const QString &label );
QMap<int, QString> mIdLabelMap;
QMap<QString, int> mLabelIdMap;
static Qtopia::UidGen &uidGen() { return sUidGen; }
static Qtopia::UidGen sUidGen;
};
/* Map from application name to categories */
class QPC_EXPORT Categories : public QObject
{
Q_OBJECT
public:
Categories( QObject *parent=0, const char *name = 0 )
: QObject( parent, name ), mGlobalCats(), mAppCats() { }
Categories( const Categories &copyFrom ) : QObject( copyFrom.parent() ),
mGlobalCats( copyFrom.mGlobalCats ),
mAppCats( copyFrom.mAppCats ) { }
virtual ~Categories() { }
Categories &operator= ( const Categories &c )
{ mAppCats = c.mAppCats; mGlobalCats = c.mGlobalCats; return *this; }
void clear();
/** Add the category name as long as it doesn't already exist
* locally or globally. Return UID if added, 0 if conflicts
* (error).
*/
int addCategory( const QString &appname, const QString &catname);
/** Add the category name as long as it doesn't already exist
* locally or globally. Return UID if added, 0 if conflicts
* (error).
*/
int addCategory( const QString &appname, const QString &catname, int uid);
/** Add the global category just checking that it doesn't
* already exist globally. Return UID if added, 0 if conflicts.
*/
int addGlobalCategory( const QString &catname );
/** Add the global category just checking that it doesn't
* already exist globally. Return UID if added, 0 if conflicts.
*/
int addGlobalCategory( const QString &catname, int uid );
/** Removes the category from the application; if it is not found
* in the application, then it removes it from the global list
*/
bool removeCategory( const QString &appName, const QString &catName,
bool checkGlobal = TRUE);
bool removeCategory( const QString &appName, int uid );
bool removeGlobalCategory( const QString &catName );
bool removeGlobalCategory( int uid );
QArray<int> ids( const QString &app, const QStringList &labels) const;
/** Returns the id associated with the app */
int id( const QString &app, const QString &cat ) const;
/** Returns the label associated with the id */
QString label( const QString &app, int id ) const;
enum ExtraLabels { NoExtra, AllUnfiled, AllLabel, UnfiledLabel };
/** Returns the sorted list of all categories that are
* associated with the app.
* If includeGlobal parameter is TRUE then the returned
* categories will include the global category items.
* If extra = NoExtra, then
* If extra = AllUnfiled, then All and Unfiled will be prepended to
* the list
* If extra = AllLabel, then All is prepended
* If extra = UnfiledLabel, then Unfiled is prepended
*/
QStringList labels( const QString &app,
bool includeGlobal = TRUE,
ExtraLabels extra = NoExtra ) const;
QStringList labels( const QString &app,
const QArray<int> &catids ) const;
enum DisplaySingle { ShowMulti, ShowAll, ShowFirst };
/** Returns a single string associated with the cat ids for display in
* a combobox or any area that requires one string. If catids are empty
* then "Unfiled" will be returned. If multiple categories are assigned
* then the behavior depends on the DisplaySingle type.
* If /a display is set to ShowMulti then " (multi)" appended to the
* first string. If /a display is set to ShowAll, then a space seperated
* string is returned with all categories. If ShowFirst is returned,
* the just the first string is returned.
*/
QString displaySingle( const QString &app,
const QArray<int> &catids,
DisplaySingle display ) const;
QStringList globalCategories() const { return mGlobalCats.labels();}
bool renameCategory( const QString &appname,
const QString &oldName,
const QString &newName );
bool renameGlobalCategory( const QString &oldName,
const QString &newName );
void setGlobal( const QString &appname, const QString &catname,
bool value );
bool isGlobal( const QString &catname ) const;
/** Returns true if the catname is associated with any application
*/
bool exists( const QString &catname ) const;
bool exists( const QString &appname, const QString &catname) const;
bool save( const QString &fname ) const;
bool load( const QString &fname );
// for debugging
void dump() const;
const QMap<QString, CategoryGroup> &appGroupMap() const{ return mAppCats; }
const CategoryGroup &globalGroup() const { return mGlobalCats; }
signals:
/** emitted if added a category;
* the second param is the application the category was added to
* or null if global
* the third param is the uid of the newly added category
*/
void categoryAdded( const Categories &, const QString &, int );
/** emitted if removed a category
* the second param is the application the category was removed from
* or null if global
* the third param is the uid of the removed category
*/
void categoryRemoved( const Categories &, const QString &, int );
/** emitted if a category is renamed; the second param is the uid of
* the removed category */
void categoryRenamed( const Categories &, const QString &, int );
private:
CategoryGroup mGlobalCats;
QMap< QString, CategoryGroup > mAppCats;
};
class QPC_EXPORT CheckedListView : public QListView
{
public:
void addCheckableList( const QStringList &options );
void setChecked( const QStringList &checked );
QStringList checked() const;
};
#endif
diff --git a/library/global.cpp b/library/global.cpp
index ec87555..f7a0767 100644
--- a/library/global.cpp
+++ b/library/global.cpp
@@ -427,386 +427,435 @@ void Global::showInputMethod()
}
/*!
Explicitly hide the current input method.
The current input method is still indicated in the taskbar, but no
longer takes up screen space, and can no longer be interacted with.
\sa showInputMethod()
*/
void Global::hideInputMethod()
{
#if !defined(QT_NO_COP)
QCopChannel::send( "QPE/TaskBar", "hideInputMethod()" );
#endif
}
/*!
\internal
*/
bool Global::isBuiltinCommand( const QString &name )
{
if(!builtin)
return FALSE; // yes, it can happen
for (int i = 0; builtin[i].file; i++) {
if ( builtin[i].file == name ) {
return TRUE;
}
}
return FALSE;
}
Global::Command* Global::builtin=0;
QGuardedPtr<QWidget> *Global::running=0;
/*!
\class Global::Command
\brief The Global::Command class is internal.
\internal
*/
/*!
\internal
*/
void Global::setBuiltinCommands( Command* list )
{
if ( running )
delete [] running;
builtin = list;
int count = 0;
if (!builtin)
return;
while ( builtin[count].file )
count++;
running = new QGuardedPtr<QWidget> [ count ];
}
/*!
\internal
*/
void Global::setDocument( QWidget* receiver, const QString& document )
{
Emitter emitter(receiver,document);
}
/*!
\internal
*/
bool Global::terminateBuiltin( const QString& n )
{
if (!builtin)
return FALSE;
for (int i = 0; builtin[i].file; i++) {
if ( builtin[i].file == n ) {
delete running[i];
return TRUE;
}
}
return FALSE;
}
/*!
\internal
*/
void Global::terminate( const AppLnk* app )
{
//if ( terminateBuiltin(app->exec()) ) return; // maybe? haven't tried this
#ifndef QT_NO_COP
QCString channel = "QPE/Application/" + app->exec().utf8();
if ( QCopChannel::isRegistered(channel) ) {
QCopEnvelope e(channel, "quit()");
}
#endif
}
/*!
Low-level function to run command \a c.
\warning Do not use this function. Use execute instead.
\sa execute()
*/
void Global::invoke(const QString &c)
{
// Convert the command line in to a list of arguments
QStringList list = QStringList::split(QRegExp(" *"),c);
#if !defined(QT_NO_COP)
QString ap=list[0];
// see if the application is already running
// XXX should lock file /tmp/qcop-msg-ap
if ( QCopChannel::isRegistered( ("QPE/Application/" + ap).latin1() ) ) {
// If the channel is already register, the app is already running, so show it.
{ QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "raise()" ); }
//QCopEnvelope e("QPE/System", "notBusy(QString)" );
//e << ap;
return;
}
// XXX should unlock file /tmp/qcop-msg-ap
//see if it is being started
if ( StartingAppList::isStarting( ap ) ) {
// FIXME take it out for now, since it leads to a much to short showing of wait if
// some entry is clicked.
// Real cause is that ::execute is called twice for document tab. But it would need some larger changes
// to fix that, and with future syncs with qtopia 1.6 it will change anyway big time since somebody there
// had the idea that an apploader belongs to the launcher ...
//QCopEnvelope e("QPE/System", "notBusy(QString)" );
//e << ap;
return;
}
#endif
#ifdef QT_NO_QWS_MULTIPROCESS
QMessageBox::warning( 0, "Error", "Could not find the application " + c, "Ok", 0, 0, 0, 1 );
#else
QStrList slist;
unsigned int j;
for ( j = 0; j < list.count(); j++ )
slist.append( list[j].utf8() );
const char **args = new const char *[slist.count() + 1];
for ( j = 0; j < slist.count(); j++ )
args[j] = slist.at(j);
args[j] = NULL;
#if !defined(QT_NO_COP)
// an attempt to show a wait...
// more logic should be used, but this will be fine for the moment...
QCopEnvelope ( "QPE/System", "busy()" );
#endif
#ifdef HAVE_QUICKEXEC
#ifdef Q_OS_MACX
QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".dylib";
#else
QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so";
#endif
qDebug("libfile = %s", libexe.latin1() );
if ( QFile::exists( libexe ) ) {
qDebug("calling quickexec %s", libexe.latin1() );
quickexecv( libexe.utf8().data(), (const char **)args );
} else
#endif
{
bool success = false;
int pfd [2];
if ( ::pipe ( pfd ) < 0 )
pfd [0] = pfd [1] = -1;
pid_t pid = ::fork ( );
if ( pid == 0 ) { // child
for ( int fd = 3; fd < 100; fd++ ) {
if ( fd != pfd [1] )
::close ( fd );
}
::setpgid ( ::getpid ( ), ::getppid ( ));
// Closing of fd[1] indicates that the execvp succeeded!
if ( pfd [1] >= 0 )
::fcntl ( pfd [1], F_SETFD, FD_CLOEXEC );
// Try bindir first, so that foo/bar works too
::execv ( qpeDir ( ) + "/bin/" + args [0], (char * const *) args );
::execvp ( args [0], (char * const *) args );
char resultByte = 1;
if ( pfd [1] >= 0 )
::write ( pfd [1], &resultByte, 1 );
::_exit ( -1 );
}
else if ( pid > 0 ) {
success = true;
if ( pfd [1] >= 0 )
::close ( pfd [1] );
if ( pfd [0] >= 0 ) {
while ( true ) {
char resultByte;
int n = ::read ( pfd [0], &resultByte, 1 );
if ( n == 1 ) {
success = false;
break;
}
if (( n == -1 ) && (( errno == ECHILD ) || ( errno == EINTR )))
continue;
break; // success
}
::close ( pfd [0] );
}
}
if ( success )
StartingAppList::add( list[0] );
else
QMessageBox::warning( 0, "Error", "Could not start the application " + c, "Ok", 0, 0, 0, 1 );
}
#endif //QT_NO_QWS_MULTIPROCESS
}
/*!
Executes the application identfied by \a c, passing \a
document if it isn't null.
Note that a better approach might be to send a QCop message to the
application's QPE/Application/\e{appname} channel.
*/
void Global::execute( const QString &c, const QString& document )
{
// ask the server to do the work
#if !defined(QT_NO_COP)
if ( document.isNull() ) {
QCopEnvelope e( "QPE/System", "execute(QString)" );
e << c;
} else {
QCopEnvelope e( "QPE/System", "execute(QString,QString)" );
e << c << document;
}
#endif
return;
}
/*!
Returns the string \a s with the characters '\', '"', and '$' quoted
by a preceeding '\'.
\sa stringQuote()
*/
QString Global::shellQuote(const QString& s)
{
QString r="\"";
for (int i=0; i<(int)s.length(); i++) {
char c = s[i].latin1();
switch (c) {
case '\\': case '"': case '$':
r+="\\";
}
r += s[i];
}
r += "\"";
return r;
}
/*!
Returns the string \a s with the characters '\' and '"' quoted by a
preceeding '\'.
\sa shellQuote()
*/
QString Global::stringQuote(const QString& s)
{
QString r="\"";
for (int i=0; i<(int)s.length(); i++) {
char c = s[i].latin1();
switch (c) {
case '\\': case '"':
r+="\\";
}
r += s[i];
}
r += "\"";
return r;
}
/*!
Finds all documents on the system's document directories which
match the filter \a mimefilter, and appends the resulting DocLnk
objects to \a folder.
*/
void Global::findDocuments(DocLnkSet* folder, const QString &mimefilter)
{
QString homedocs = QString(getenv("HOME")) + "/Documents";
DocLnkSet d(homedocs,mimefilter);
folder->appendFrom(d);
/** let's do intellegint way of searching these files
* a) the user don't want to check mediums global
* b) the user wants to check but use the global options for it
* c) the user wants to check it but not this medium
* d) the user wants to check and this medium as well
*
* In all cases we need to apply a different mimefilter to
* the medium.
* a) mimefilter.isEmpty() we need to apply the responding filter
* either the global or the one on the medium
*
* b) mimefilter is set to an application we need to find out if the
* mimetypes are included in the mime mask of the medium
*/
StorageInfo storage;
const QList<FileSystem> &fs = storage.fileSystems();
QListIterator<FileSystem> it ( fs );
for ( ; it.current(); ++it ) {
if ( (*it)->isRemovable() ) { // let's find out if we should search on it
// this is a candidate look at the cf and see if we should search on it
QString path = (*it)->path();
Config conf((*it)->path() + "/.opiestorage.cf", Config::File );
conf.setGroup("main");
if (!conf.readBoolEntry("check",true)) {
continue;
}
conf.setGroup("subdirs");
if (conf.readBoolEntry("wholemedia",true)) {
DocLnkSet ide( path,mimefilter);
folder->appendFrom(ide);
} else {
QStringList subDirs = conf.readListEntry("subdirs",':');
if (subDirs.isEmpty()) {
subDirs.append("Documents");
}
for (unsigned c = 0; c < subDirs.count();++c) {
DocLnkSet ide( path+"/"+subDirs[c], mimefilter );
folder->appendFrom(ide);
}
}
} else if ( (*it)->disk() == "/dev/mtdblock6" || (*it)->disk() == "tmpfs" ) {
QString path = (*it)->path() + "/Documents";
DocLnkSet ide( path, mimefilter );
folder->appendFrom(ide);
}
}
}
QStringList Global::languageList()
{
QString lang = getenv("LANG");
QStringList langs;
langs.append(lang);
int i = lang.find(".");
if ( i > 0 )
lang = lang.left( i );
i = lang.find( "_" );
if ( i > 0 )
langs.append(lang.left(i));
return langs;
}
QStringList Global::helpPath()
{
QString qpeDir = QPEApplication::qpeDir();
QStringList path;
QStringList langs = Global::languageList();
for (QStringList::ConstIterator it = langs.fromLast(); it!=langs.end(); --it) {
QString lang = *it;
if ( !lang.isEmpty() )
path += qpeDir + "/help/" + lang + "/html";
}
path += qpeDir + "/pics";
path += qpeDir + "/help/html";
/* we even put english into the en dir so try it as fallback as well for opie */
path += qpeDir + "/help/en/html";
path += qpeDir + "/docs";
return path;
}
+/*!
+ \internal
+ Truncate file to size specified
+ \a f must be an open file
+ \a size must be a positive value
+ */
+bool Global::truncateFile(QFile &f, int size){
+ if (!f.isOpen())
+ return FALSE;
+
+ return ::ftruncate(f.handle(), size) != -1;
+}
+
+
+
+
+// #if defined(Q_OS_UNIX) && defined(Q_WS_QWS)
+// extern int qws_display_id;
+// #endif
+
+/*!
+ /internal
+ Returns the default system path for storing temporary files.
+ Note: This does not it ensure that the provided directory exists
+*/
+QString Global::tempDir()
+{
+ QString result;
+#ifdef Q_OS_UNIX
+#ifdef Q_WS_QWS
+ result = QString("/tmp/qtopia-%1/").arg(QString::number(qws_display_id));
+#else
+ result="/tmp/";
+#endif
+#else
+ if (getenv("TEMP"))
+ result = getenv("TEMP");
+ else
+ result = getenv("TMP");
+
+ if (result[(int)result.length() - 1] != QDir::separator())
+ result.append(QDir::separator());
+#endif
+
+ return result;
+}
+
+//#endif
+
#include "global.moc"
diff --git a/library/global.h b/library/global.h
index 1136b12..f32c498 100644
--- a/library/global.h
+++ b/library/global.h
@@ -1,90 +1,94 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef GLOBAL_H
#define GLOBAL_H
#include <qstringlist.h>
#include <qguardedptr.h>
class QDawg;
class QLabel;
class QWidget;
class AppLnk;
class DocLnkSet;
-
+class QFile;
class Global
{
public:
Global();
// Dictionaries
static const QDawg& fixedDawg();
static const QDawg& addedDawg();
static const QDawg& dawg(const QString& name);
static void addWords(const QStringList& word);
static void addWords(const QString& dictname, const QStringList& word);
// static void removeWords(const QStringList& word); -- if someone wants it
static void createDocDir();
static void findDocuments(DocLnkSet* folder, const QString &mimefilter=QString::null);
static QString applicationFileName(const QString& appname, const QString& filename);
struct Command {
const char *file;
QWidget *(*func)( bool );
bool maximized;
bool documentary;
};
static void setBuiltinCommands( Command* );
static void execute( const QString &exec, const QString &document=QString::null );
static void setDocument( QWidget* receiver, const QString& document );
static bool terminateBuiltin( const QString& );
static void terminate( const AppLnk* );
static bool isBuiltinCommand( const QString &name );
// system messaging
static void applyStyle();
static void statusMessage(const QString&);
static QWidget *shutdown( bool = FALSE );
static QWidget *restart( bool = FALSE );
static void hideInputMethod();
static void showInputMethod();
static void writeHWClock();
static QString shellQuote(const QString& s);
static QString stringQuote(const QString& s);
#ifdef QTOPIA_INTERNAL_LANGLIST
static QStringList languageList();
static QStringList helpPath();
#endif
+//#ifdef QTOPIA_INTERNAL_FILEOPERATIONS
+ static bool truncateFile(QFile &f, int size);
+ static QString tempDir( );
+//#endif
private:
static void invoke( const QString &exec);
static Command* builtin;
static QGuardedPtr<QWidget> *running;
};
#endif
diff --git a/library/library.pro b/library/library.pro
index 7143454..4142529 100644
--- a/library/library.pro
+++ b/library/library.pro
@@ -1,141 +1,143 @@
TEMPLATE = lib
#CONFIG += qt warn_on release
CONFIG += qt warn_on debug
HEADERS = calendar.h \
global.h \
resource.h \
xmlreader.h \
mimetype.h \
menubutton.h \
network.h \
networkinterface.h \
filemanager.h \
fontmanager.h \
qdawg.h \
datebookmonth.h \
fileselector.h \
fileselector_p.h \
imageedit.h \
qcopenvelope_qws.h \
qpedecoration_qws.h \
qpeapplication.h \
qpestyle.h \
qpedialog.h \
lightstyle.h \
config.h \
applnk.h \
sound.h \
tzselect.h \
qmath.h \
datebookdb.h \
alarmserver.h \
process.h \
password.h \
timestring.h \
fontfactoryinterface.h \
fontdatabase.h \
power.h \
storage.h \
qpemessagebox.h \
timeconversion.h \
qpedebug.h \
qpemenubar.h \
qpetoolbar.h \
backend/categories.h \
stringutil.h \
backend/palmtoprecord.h \
backend/task.h \
backend/event.h \
backend/contact.h\
categorymenu.h \
categoryedit_p.h \
categoryselect.h \
categorywidget.h \
ir.h \
backend/vobject_p.h \
findwidget_p.h \
finddialog.h \
lnkproperties.h \
windowdecorationinterface.h \
textcodecinterface.h \
imagecodecinterface.h \
+ locationcombo.h \
qpeglobal.h
SOURCES = calendar.cpp \
global.cpp \
xmlreader.cpp \
mimetype.cpp \
menubutton.cpp \
network.cpp \
networkinterface.cpp \
filemanager.cpp \
fontmanager.cpp \
qdawg.cpp \
datebookmonth.cpp \
fileselector.cpp \
imageedit.cpp \
resource.cpp \
qpedecoration_qws.cpp \
qcopenvelope_qws.cpp \
qpeapplication.cpp \
qpestyle.cpp \
qpedialog.cpp \
lightstyle.cpp \
config.cpp \
applnk.cpp \
sound.cpp \
tzselect.cpp \
qmath.c \
datebookdb.cpp \
alarmserver.cpp \
password.cpp \
process.cpp \
process_unix.cpp \
timestring.cpp \
fontdatabase.cpp \
power.cpp \
storage.cpp \
qpemessagebox.cpp \
backend/timeconversion.cpp \
qpedebug.cpp \
qpemenubar.cpp \
qpetoolbar.cpp \
backend/categories.cpp \
backend/stringutil.cpp \
backend/palmtoprecord.cpp \
backend/task.cpp \
backend/event.cpp \
backend/contact.cpp \
categorymenu.cpp \
categoryedit_p.cpp \
categoryselect.cpp \
categorywidget.cpp \
ir.cpp \
backend/vcc_yacc.cpp \
backend/vobject.cpp \
findwidget_p.cpp \
finddialog.cpp \
lnkproperties.cpp \
+ locationcombo.cpp \
widget_showing.cpp
# Qt 3 compatibility
HEADERS += quuid.h qcom.h qlibrary.h qlibrary_p.h
SOURCES += quuid.cpp qlibrary.cpp qlibrary_unix.cpp
DEFINES += OPIE_INTERNAL_LIBRARY_BUILD
INCLUDEPATH += $(OPIEDIR)/include backend
LIBS += -ldl -lcrypt -lm
INTERFACES = passwordbase_p.ui categoryeditbase_p.ui findwidgetbase_p.ui lnkpropertiesbase_p.ui
TARGET = qpe
DESTDIR = $(OPIEDIR)/lib$(PROJMAK)
VERSION = 1.5.0.1
include( $(OPIEDIR)/include.pro )
contains( CONFIG, LIBQPE_WITHROHFEEDBACK ){
DEFINES += OPIE_WITHROHFEEDBACK
SOURCES += backend/rohfeedback.cpp
HEADERS += backend/rohfeedback.h
}
diff --git a/library/locationcombo.cpp b/library/locationcombo.cpp
new file mode 100644
index 0000000..31429f5
--- a/dev/null
+++ b/library/locationcombo.cpp
@@ -0,0 +1,295 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "locationcombo.h"
+
+#include <qpe/ir.h>
+#include <qpe/applnk.h>
+#include <qpe/global.h>
+#include <qpe/categorywidget.h>
+#include <qpe/categoryselect.h>
+#ifdef QWS
+#include <qpe/qcopenvelope_qws.h>
+#endif
+#include <qpe/filemanager.h>
+#include <qpe/config.h>
+#include <qpe/storage.h>
+#include <qpe/global.h>
+#include <qtopia/qpemessagebox.h>
+
+#include <qlineedit.h>
+#include <qtoolbutton.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qmessagebox.h>
+#include <qsize.h>
+#include <qcombobox.h>
+#include <qregexp.h>
+
+#include <qradiobutton.h>
+#include <qlayout.h>
+
+#include <stdlib.h>
+
+/*!
+ \class LocationCombo locationcombo.h
+ \brief The LocationCombo class displays a list of available storage
+ locations.
+
+ First availability: Qtopia 1.6
+
+ \ingroup qtopiaemb
+ \sa DocPropertiesDialog
+ */
+
+
+class LocationComboPrivate
+{
+public:
+ LocationComboPrivate() : homeLocation(-1), fileSize(0), listEmpty(TRUE) {}
+ QString originalPath;
+ int homeLocation;
+ int fileSize;
+ bool listEmpty;
+};
+
+/*!
+ Constructs a LocationCombo with parent \a parent and name \a name.
+ */
+LocationCombo::LocationCombo( QWidget *parent, const char *name )
+ : QComboBox( FALSE, parent, name )
+{
+ storage = new StorageInfo;
+ d = new LocationComboPrivate;
+ setLocation( 0 );
+ connect( this, SIGNAL(activated(int)), this, SIGNAL(newPath()) );
+ connect( storage, SIGNAL(disksChanged()), this, SLOT(updatePaths()) );
+}
+
+/*!
+ Constructs a LocationCombo with parent \a parent and name \a name.
+ \a lnk is pointer to an existing AppLnk.
+ */
+LocationCombo::LocationCombo( const AppLnk * lnk, QWidget *parent, const char *name )
+ : QComboBox( FALSE, parent, name )
+{
+ storage = new StorageInfo;
+ d = new LocationComboPrivate;
+ setLocation(lnk);
+ connect( this, SIGNAL(activated(int)), this, SIGNAL(newPath()) );
+ connect( storage, SIGNAL(disksChanged()), this, SLOT(updatePaths()) );
+}
+
+/*!
+ Destroys the widget.
+ */
+LocationCombo::~LocationCombo()
+{
+ delete storage;
+ delete d;
+}
+
+/*!
+ Sets the display of the LocationCombo to the location associated with the
+ AppLnk \a lnk.
+ */
+void LocationCombo::setLocation( const AppLnk * lnk )
+{
+ // NB: setLocation(const QString) assumes only lnk->file() is used.
+
+ if ( lnk ) {
+ QFileInfo fi( lnk->file() );
+ d->fileSize = fi.size();
+ const FileSystem *fs = storage->fileSystemOf( lnk->file() );
+ d->originalPath = fs ? fs->path() : QString::null;
+ } else {
+ d->fileSize = 0;
+ d->originalPath = QString::null;
+ }
+
+ setupCombo();
+
+ int currentLocation = -1;
+ if ( lnk ) {
+ int n = locations.count();
+ for ( int i = 0; i < n; i++ ) {
+ if ( lnk->file().contains( locations[i] ) )
+ currentLocation = i;
+ }
+ }
+ if ( currentLocation == -1 )
+ currentLocation = 0; //default to the first one
+
+ setCurrentItem( currentLocation );
+}
+
+/*!
+ \internal
+*/
+void LocationCombo::setupCombo()
+{
+ clear();
+ locations.clear();
+
+ const QList<FileSystem> &fs = storage->fileSystems();
+ QListIterator<FileSystem> it ( fs );
+ QString s;
+ QString homeDir = QDir::homeDirPath();
+ QString homeFs;
+ QString homeFsPath;
+ int index = 0;
+ for ( ; it.current(); ++it ) {
+ // we add 10k to the file size so we are sure we can also save the desktop file
+ if ( !d->fileSize || (*it)->path() == d->originalPath ||
+ (ulong)(*it)->availBlocks() * (ulong)(*it)->blockSize()
+ > (ulong)d->fileSize + 10000 )
+ {
+ if ( (*it)->isRemovable() ) {
+ insertItem( (*it)->name(), index );
+ locations.append( (*it)->path() );
+ index++;
+ } else if ( homeDir.contains( (*it)->path() ) &&
+ (*it)->path().length() > homeFsPath.length() ) {
+ homeFs = (*it)->name();
+ homeFsPath = (*it)->path();
+ }
+ }
+ }
+
+ // $HOME is *somewhere*, but not shown in Storage::fileSystems(),
+ // eg. because it's mounted in some unexpected way.
+ if ( homeFsPath.isEmpty() ) {
+ homeFs = StorageInfo::tr("Internal Storage");
+ homeFsPath = homeDir;
+ }
+
+ if ( !homeFsPath.isEmpty() ) {
+ d->homeLocation = 0;
+ insertItem( homeFs, d->homeLocation );
+ locations.prepend( homeDir );
+ } else {
+ d->homeLocation = -1;
+ }
+
+ d->listEmpty = locations.count() == 0;
+ if ( d->listEmpty ) {
+ insertItem( tr("No FileSystems Available!"), 0 );
+ locations.append( "" );
+ }
+}
+
+/*!
+ \internal
+ */
+void LocationCombo::updatePaths()
+{
+ QString oldPath = locations[currentItem()];
+
+ setupCombo();
+
+ int currentLocation = 0;
+ int n = locations.count();
+ for ( int i = 0; i < n; i++ ) {
+ if ( oldPath == locations[i] ) {
+ currentLocation = i;
+ }
+ }
+ setCurrentItem( currentLocation );
+ if ( locations[currentItem()] != oldPath )
+ emit newPath();
+}
+
+/*!
+ Returns TRUE to indicate that the user has changed the location displayed
+ by the LocationCombo. Most useful when the LocationCombo is part of a
+ dialog; when the dialog is accept()ed, LocationCombo::isChanged() can be
+ examined to check for a change of location.
+ */
+bool LocationCombo::isChanged() const
+{
+ if ( const FileSystem *fs = storage->fileSystemOf(locations[currentItem()]) )
+ return fs->path() != d->originalPath;
+
+ return TRUE;
+}
+
+/*!
+ Returns the default (home) location for the file associated with this
+ LocationCombo.
+ */
+QString LocationCombo::installationPath() const
+{
+ return currentItem() == d->homeLocation ?
+ QString("/") : locations[ currentItem() ]+"/";
+}
+
+/*!
+ Returns the document path associated with this LocationCombo. This
+ will be "\<path\>/Documents".
+ */
+QString LocationCombo::documentPath() const
+{
+ return locations[ currentItem() ]+"/Documents/";
+}
+
+/*!
+ Returns a pointer to FileSystem object, associated with the current
+ selection of the LocationCombo.
+ */
+const FileSystem *LocationCombo::fileSystem() const
+{
+ if ( d->listEmpty )
+ return 0;
+ return storage->fileSystemOf( locations[ currentItem() ] );
+}
+
+/*!
+ \fn LocationCombo::newPath()
+ Emitted when the LocationCombo changes to a new location.
+ */
+
+
+#if 0
+void LocationCombo::apply()
+{
+}
+#endif
+
diff --git a/library/locationcombo.h b/library/locationcombo.h
new file mode 100644
index 0000000..fab3dfc
--- a/dev/null
+++ b/library/locationcombo.h
@@ -0,0 +1,88 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef LOCATIONCOMBO_H
+#define LOCATIONCOMBO_H
+
+#include <qpe/qpeglobal.h>
+
+#ifdef Q_WS_QWS
+
+#include <qstringlist.h>
+#include <qcombobox.h>
+
+class AppLnk;
+class QListViewItem;
+class DocLnk;
+class FileSystem;
+class StorageInfo;
+
+
+class LocationComboPrivate;
+
+class LocationCombo : public QComboBox
+{
+ Q_OBJECT
+public:
+ LocationCombo( QWidget *parent, const char *name=0 );
+ LocationCombo( const AppLnk * lnk, QWidget *parent, const char *name=0 );
+
+ ~LocationCombo();
+
+ void setLocation( const QString& path ); // qtopia 2
+ void setLocation( const AppLnk * );
+
+ QString installationPath() const;
+ QString documentPath() const;
+ const FileSystem *fileSystem() const;
+
+ bool isChanged() const;
+
+signals:
+ void newPath();
+
+private slots:
+ void updatePaths();
+
+private:
+ void setupCombo();
+ QStringList locations;
+ StorageInfo *storage;
+ LocationComboPrivate *d;
+};
+
+
+#endif // QWS
+#endif // LNKPROPERTIES_H
diff --git a/library/qlibrary_unix.cpp b/library/qlibrary_unix.cpp
index fee73c2..f4d60cb 100644
--- a/library/qlibrary_unix.cpp
+++ b/library/qlibrary_unix.cpp
@@ -1,243 +1,243 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "qlibrary_p.h"
#ifndef QT_NO_COMPONENT
/*
The platform dependent implementations of
- loadLibrary
- freeLibrary
- resolveSymbol
It's not too hard to guess what the functions do.
*/
#if defined(Q_OS_HPUX)
// for HP-UX < 11.x and 32 bit
#include <dl.h>
bool QLibraryPrivate::loadLibrary()
{
if ( pHnd )
return TRUE;
QString filename = library->library();
pHnd = (void*)shl_load( filename.latin1(), BIND_DEFERRED | BIND_NONFATAL | DYNAMIC_PATH, 0 );
#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
if ( !pHnd )
qDebug( "Failed to load library %s!", filename.latin1() );
#endif
return pHnd != 0;
}
bool QLibraryPrivate::freeLibrary()
{
if ( !pHnd )
return TRUE;
if ( !shl_unload( (shl_t)pHnd ) ) {
pHnd = 0;
return TRUE;
}
return FALSE;
}
void* QLibraryPrivate::resolveSymbol( const char* symbol )
{
if ( !pHnd )
return 0;
void* address = 0;
if ( shl_findsym( (shl_t*)&pHnd, symbol, TYPE_UNDEFINED, address ) < 0 ) {
#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
qDebug( "Couldn't resolve symbol \"%s\"", symbol );
#endif
return 0;
}
return address;
}
#elif defined(_NULL_LIB_)
bool QLibraryPrivate::loadLibrary()
{
//qDebug("QLibraryPrivate::loadLibrary\n");
return FALSE;
}
bool QLibraryPrivate::freeLibrary()
{
//qDebug("QLibraryPrivate::freeLibrary\n");
return FALSE;
}
void* QLibraryPrivate::resolveSymbol( const char* symbol )
{
//qDebug("QLibraryPrivate::resolveSymbol\n");
return FALSE;
}
#elif defined(Q_OS_MACX)
#define ENUM_DYLD_BOOL
enum DYLD_BOOL {
DYLD_FALSE,
DYLD_TRUE
};
#include <mach-o/dyld.h>
typedef struct {
NSObjectFileImage img;
NSModule mod;
} DyldLibDesc;
bool QLibraryPrivate::loadLibrary()
{
// qDebug("QLibraryPrivate::loadLibrary\n");
// return FALSE;
if ( pHnd )
return TRUE;
QString filename = library->library();
NSObjectFileImage img = 0;
NSModule mod = 0;
NSObjectFileImageReturnCode ret = NSCreateObjectFileImageFromFile( filename.latin1() , &img );
if ( ret != NSObjectFileImageSuccess ) {
qWarning( "Error in NSCreateObjectFileImageFromFile(): %d; Filename: %s", ret, filename.latin1() );
if (ret == NSObjectFileImageAccess) {
qWarning ("(NSObjectFileImageAccess)" );
}
} else {
mod = NSLinkModule(img, filename.latin1(), NSLINKMODULE_OPTION_BINDNOW |
NSLINKMODULE_OPTION_PRIVATE |
NSLINKMODULE_OPTION_RETURN_ON_ERROR);
if (mod == 0) {
qWarning( "Error in NSLinkModule()" );
NSDestroyObjectFileImage(img);
}
}
DyldLibDesc* desc = 0;
if (img != 0 && mod != 0) {
desc = new DyldLibDesc;
desc->img = img;
desc->mod = mod;
}
pHnd = desc;
return pHnd != 0;
}
bool QLibraryPrivate::freeLibrary()
{
//qDebug("QLibraryPrivate::freeLibrary\n");
//return FALSE;
if ( !pHnd )
return TRUE;
DyldLibDesc* desc = (DyldLibDesc*) pHnd;
NSModule mod = desc->mod;
NSObjectFileImage img = desc->img;
bool success = NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE);
if ( success ) {
NSDestroyObjectFileImage(img);
delete desc;
pHnd = 0;
}
#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
else {
qWarning( "Error in NSUnLinkModule()" );
}
#endif
return pHnd == 0;
}
void* QLibraryPrivate::resolveSymbol( const char* symbol )
{
//qDebug("QLibraryPrivate::resolveSymbol\n");
//return FALSE;
if ( !pHnd )
return 0;
DyldLibDesc* desc = (DyldLibDesc*) pHnd;
NSSymbol sym = NSLookupSymbolInModule(desc->mod, symbol);
void* address = 0;
if (sym != 0) {
address = NSAddressOfSymbol(sym);
}
#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
if ( address == 0 )
qWarning( "Cannot find symbol: %s", symbol );
#endif
return address;
}
#else
// Something else, assuming POSIX
#include <dlfcn.h>
bool QLibraryPrivate::loadLibrary()
{
if ( pHnd )
return TRUE;
QString filename = library->library();
- pHnd = dlopen( filename.latin1() , RTLD_LAZY );
+ pHnd = ::dlopen( filename.latin1() , RTLD_LAZY );
// #if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
if ( !pHnd )
qWarning( "%s", dlerror() );
// #endif
return pHnd != 0;
}
bool QLibraryPrivate::freeLibrary()
{
if ( !pHnd )
return TRUE;
- int ec = dlclose( pHnd );
+ int ec = ::dlclose( pHnd );
if ( !ec )
pHnd = 0;
#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
else {
const char* error = dlerror();
if ( error )
qWarning( "%s", error );
}
#endif
return pHnd == 0;
}
void* QLibraryPrivate::resolveSymbol( const char* f )
{
if ( !pHnd )
return 0;
void* address = dlsym( pHnd, f );
#if defined(QT_DEBUG) || defined(QT_DEBUG_COMPONENT)
const char* error = dlerror();
if ( error )
qWarning( "%s", error );
#endif
return address;
}
#endif // POSIX
#endif // QT_NO_COMPONENT
diff --git a/library/timestring.cpp b/library/timestring.cpp
index 91c29ae..afd162d 100644
--- a/library/timestring.cpp
+++ b/library/timestring.cpp
@@ -1,365 +1,466 @@
/**********************************************************************
-** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file.
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
-** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "timestring.h"
#include <qobject.h>
-#include <qpe/qpeapplication.h> //for qApp
+#include <qdatetime.h>
+#include <qapplication.h>
#include "config.h"
+#include <time.h>
+
-class TimeStringFormatKeeper : public QObject
+class TimeStringFormat : public QObject
{
Q_OBJECT
public:
static DateFormat currentFormat()
{
if ( !self )
- self = new TimeStringFormatKeeper;
+ self = new TimeStringFormat;
return self->format;
}
private slots:
void formatChanged( DateFormat f )
{
format = f;
}
private:
- static TimeStringFormatKeeper *self;
+ static TimeStringFormat *self;
DateFormat format;
- TimeStringFormatKeeper()
+ TimeStringFormat()
: QObject( qApp )
{
Config config("qpe");
config.setGroup( "Date" );
- format = DateFormat(QChar(config.readEntry("Separator", "/")[0]),
- (DateFormat::Order)config .readNumEntry("ShortOrder", DateFormat::DayMonthYear),
- (DateFormat::Order)config.readNumEntry("LongOrder", DateFormat::DayMonthYear));
+ format = ::DateFormat(QChar(config.readEntry("Separator", "/")[0]),
+ (::DateFormat::Order)config.readNumEntry("ShortOrder", ::DateFormat::DayMonthYear),
+ (::DateFormat::Order)config.readNumEntry("LongOrder", ::DateFormat::DayMonthYear));
connect( qApp, SIGNAL( dateFormatChanged(DateFormat) ),
this, SLOT( formatChanged(DateFormat) ) );
}
};
-TimeStringFormatKeeper *TimeStringFormatKeeper::self = 0;
+TimeStringFormat *TimeStringFormat::self = 0;
QString DateFormat::toNumberString() const
{
QString buf = "";
// for each part of the order
for (int i = 0; i < 3; i++) {
// switch on the relavent 3 bits.
switch((_shortOrder >> (i * 3)) & 0x0007) {
case 0x0001:
- buf += QObject::tr( "D" , "Shortcut for Day");
+ buf += TimeStringFormat::tr( "D", "first letter of the word 'Day'" );
break;
case 0x0002:
- buf += QObject::tr( "M", "Shortcur for Month" );
+ buf += TimeStringFormat::tr( "M" , "first letter of the word 'Month'" );
break;
case 0x0004:
- buf += QObject::tr( "Y" );
+ buf += TimeStringFormat::tr( "Y" , "first letter of the word 'Year'" );
break;
}
if (i < 2)
buf += _shortSeparator;
}
return buf;
}
QString DateFormat::toWordString() const
{
QString buf = "";
// for each part of the order
for (int i = 0; i < 3; i++) {
// switch on the relavent 3 bits.
switch((_longOrder >> (i * 3)) & 0x0007) {
case 0x0001:
- buf += QObject::tr( "day" );
+ buf += TimeStringFormat::tr( "day", "in month" );
if (i < 2) {
if ((_shortOrder << ((i+1) * 3)) & 0x0007)
buf += ", ";
else
buf += " ";
}
break;
case 0x0002:
- buf += QObject::tr( "month" );
+ buf += TimeStringFormat::tr( "month" );
if (i < 2)
buf += " ";
break;
case 0x0004:
- buf += QObject::tr( "year" );
+ buf += TimeStringFormat::tr( "year" );
if (i < 2)
buf += ", ";
break;
}
}
return buf;
}
QString DateFormat::numberDate(const QDate &d, int v) const
{
QString buf = "";
int pad = 2;
// for each part of the order
for (int i = 0; i < 3; i++) {
// switch on the relavent 3 bits.
switch((_shortOrder >> (i * 3)) & 0x0007) {
case 0x0001:
if (pad==2) buf += QString().sprintf("%02d",d.day());
else buf += QString().sprintf("%d",d.day());
break;
case 0x0002:
if (i==0) { // no padding with only MM/DD/YY format
pad=0;
}
if (pad==2) buf += QString().sprintf("%02d",d.month());
else buf += QString().sprintf("%d",d.month());
break;
case 0x0004:
{
int year = d.year();
if (!(v & longNumber))
year = year % 100;
buf += QString().sprintf("%02d",year);
}
break;
}
if (i < 2)
buf += _shortSeparator;
}
return buf;
}
+static const char* unTranslatedFullMonthNames[] = {
+ QT_TRANSLATE_NOOP( "QDate", "January" ),
+ QT_TRANSLATE_NOOP( "QDate", "February" ),
+ QT_TRANSLATE_NOOP( "QDate", "March" ),
+ QT_TRANSLATE_NOOP( "QDate", "April" ),
+ QT_TRANSLATE_NOOP( "QDate", "May" ),
+ QT_TRANSLATE_NOOP( "QDate", "June" ),
+ QT_TRANSLATE_NOOP( "QDate", "July" ),
+ QT_TRANSLATE_NOOP( "QDate", "August" ),
+ QT_TRANSLATE_NOOP( "QDate", "September" ),
+ QT_TRANSLATE_NOOP( "QDate", "October" ),
+ QT_TRANSLATE_NOOP( "QDate", "November" ),
+ QT_TRANSLATE_NOOP( "QDate", "December" )
+};
+
+static const char* unTranslatedFullDayNames[] = {
+ QT_TRANSLATE_NOOP( "QDate", "Monday" ),
+ QT_TRANSLATE_NOOP( "QDate", "Tuesday" ),
+ QT_TRANSLATE_NOOP( "QDate", "Wednesday" ),
+ QT_TRANSLATE_NOOP( "QDate", "Thursday" ),
+ QT_TRANSLATE_NOOP( "QDate", "Friday" ),
+ QT_TRANSLATE_NOOP( "QDate", "Saturday" ),
+ QT_TRANSLATE_NOOP( "QDate", "Sunday" )
+};
+
+#ifdef QTOPIA_DESKTOP
+//translations in qt.qm
+static const char* unTranslatedMediumDayNames[] = {
+ "Mon" , "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
+};
+
+static const char* unTranslatedMediumMonthNames[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+#endif
+
+static QString dayname(const QDate& d, bool lng)
+{
+ if (lng && qApp)
+ return qApp->translate("QDate", unTranslatedFullDayNames[d.dayOfWeek()-1]);
+ else {
+#ifdef QTOPIA_DESKTOP
+ if (qApp)
+ return qApp->translate("QDate", unTranslatedMediumDayNames[ d.dayOfWeek()-1]);
+#endif
+ return d.dayName(d.dayOfWeek());
+ }
+}
+
QString DateFormat::wordDate(const QDate &d, int v) const
{
- QString buf = "";
// for each part of the order
- if (v & showWeekDay) {
- QString weekDay = d.dayName(d.dayOfWeek());
- if (!(v & longWord)) {
- weekDay = weekDay.left(3);
- }
- buf += weekDay;
- if ((_longOrder & 0x0007) == 0x0002)
- buf += ' ';
- else
- buf += ", ";
- }
+ QString weekDay;
+ if (v & showWeekDay)
+ weekDay = ::dayname(d,(v & longWord));
+ QString date="";
+ QString sep="";
for (int i = 0; i < 3; i++) {
// switch on the relavent 3 bits.
- switch((_longOrder >> (i * 3)) & 0x0007) {
- case 0x0001:
- if (i==1) {
- buf += QString().sprintf("%02d, ",d.day());
- } else {
- buf += QString().sprintf("%2d",d.day());
- if (separator()=='.') // 2002/1/11
- buf += ". ";
- else
- buf += " ";
- }
+ int field = (_longOrder >> (i * 3)) & 0x0007;
+ if ( field && !date.isEmpty() )
+ date += sep;
+ switch (field) {
+ case 0x0001: // Day
+ {
+ QString daysuffix = TimeStringFormat::tr("@day", "day suffix - applies to some asian languages (e.g. Japanese and Trad. Chinese). If it doesn't apply to your language it has to be translated to an '@day' " );
+ if (i==1) {
+ date += QString().sprintf("%02d",d.day());
+ if (daysuffix != "@day")
+ date+=daysuffix;
+ sep = TimeStringFormat::tr(",","day-date separator") + " ";
+ } else {
+ date += QString().sprintf("%2d",d.day());
+ if (daysuffix == "@day") {
+ if (separator()=='.') // 2002/1/11
+ sep = ". ";
+ else
+ sep = " ";
+ } else {
+ date += daysuffix+" ";
+ sep = " ";
+ }
+ }
+ }
break;
- case 0x0002:
+ case 0x0002: // Month
{
- QString monthName = d.monthName(d.month());
- if (!(v & longWord)) {
- monthName = monthName.left(3);
- }
- buf += monthName;
+ QString monthName;
+
+ if (v & longWord)
+ monthName = qApp->translate("QDate", unTranslatedFullMonthNames[d.month()-1] );
+ else {
+#ifdef QTOPIA_DESKTOP
+ monthName = qApp->translate("QDate", unTranslatedMediumMonthNames[d.month()-1] );
+#else
+ monthName = d.monthName( d.month() );
+#endif
+ }
+ date += monthName;
}
- if (i < 2)
- buf += " ";
+ sep = " ";//TimeStringFormat::tr(" ","month-date separator");
break;
- case 0x0004:
+ case 0x0004: // Year
{
int year = d.year();
if (!(v & longNumber))
year = year % 100;
if (year < 10)
- buf += "0";
+ date += "0";
+
+ date += QString::number(year);
+ QString yearsuffix = TimeStringFormat::tr("@year", "year suffix - applies to some asian languages (e.g. Japanese and Trad. Chinese). If it doesn't apply to your language it has to be translated to an '@year' " );
+ if (yearsuffix != "@year")
+ date += yearsuffix;
- buf += QString::number(year);
}
- if (i < 2)
- buf += ", ";
+ sep = TimeStringFormat::tr(",","year-date seperator") + " ";
break;
}
}
- return buf;
+
+ QString r = "";
+ if ( weekDay.isEmpty() )
+ r = date;
+ else if ((_longOrder & 0x0007) == 0x0002)
+ r = TimeStringFormat::tr("%1 %2","1=Monday 2=January 12").arg(weekDay).arg(date);
+ else if ( _longOrder )
+ r = TimeStringFormat::tr("%1, %2","1=Monday 2=12 January").arg(weekDay).arg(date);
+ else
+ r = weekDay;
+ return r;
}
#ifndef QT_NO_DATASTREAM
void DateFormat::save(QDataStream &d) const
{
d << _shortSeparator.unicode();
uint v= _shortOrder;
d << v;
v = _longOrder;
d << v;
}
void DateFormat::load(QDataStream &d)
{
ushort value;
d >> value;
_shortSeparator = QChar(value);
uint v = 0;
d >> v;
_shortOrder = (Order)v;
v = 0;
d >> v;
_longOrder = (Order)v;
}
QDataStream &operator<<(QDataStream &s, const DateFormat&df)
{
df.save(s);
return s;
}
QDataStream &operator>>(QDataStream &s, DateFormat&df)
{
df.load(s);
return s;
}
#endif
QString TimeString::shortDate( const QDate &d, DateFormat dtf )
{
return dtf.wordDate(d);
}
QString TimeString::dateString( const QDate &d, DateFormat dtf )
{
- return QObject::tr( dtf.wordDate(d, DateFormat::longNumber | DateFormat::longWord) );
+ return dtf.wordDate(d, DateFormat::longNumber);
}
QString TimeString::longDateString( const QDate &d, DateFormat dtf )
{
- return QObject::tr( dtf.wordDate(d, DateFormat::showWeekDay | DateFormat::longNumber
- | DateFormat::longWord) );
+ return dtf.wordDate(d, DateFormat::showWeekDay | DateFormat::longNumber
+ | DateFormat::longWord);
}
DateFormat TimeString::currentDateFormat()
{
- return TimeStringFormatKeeper::currentFormat();
+ return TimeStringFormat::currentFormat();
}
QString TimeString::dateString( const QDateTime &dt, bool ampm, bool seconds, DateFormat dtf )
{
const QDate& d = dt.date();
const QTime& t = dt.time();
// based on QDateTime::toString()
QString buf = timeString(t,ampm,seconds);
buf += " ";
buf += longDateString( d, dtf );
return buf;
}
QString TimeString::timeString( const QTime &t, bool ampm, bool seconds )
{
if ( !ampm ) {
if ( seconds )
return t.toString();
QString r = QString::number(t.hour());
if ( t.hour() < 10 ) r.prepend( "0" );
r.append( ":" );
if ( t.minute() < 10 ) r.append( "0" );
r.append(QString::number(t.minute()));
return r;
}
// ### else the hard case that should disappear in Qt 3.0
QString argString = seconds ? "%4:%5:%6 %7" : "%4:%5 %7";
int hour = t.hour();
QString strMin = QString::number( t.minute() );
QString strSec = QString::number( t.second() );
if ( hour > 12 )
argString = argString.arg( hour - 12, 2 );
else {
if ( hour == 0 )
argString = argString.arg( 12 );
else
argString = argString.arg( hour, 2 );
}
if ( t.minute() < 10 )
strMin.prepend( "0" );
if ( t.second() < 10 )
strSec.prepend( "0" );
argString = argString.arg( strMin );
if ( seconds )
argString = argString.arg( strSec );
if ( hour >= 12 )
- argString = argString.arg( QObject::tr("PM") );
+ argString = argString.arg( TimeStringFormat::tr("PM") );
else
- argString = argString.arg( QObject::tr("AM") );
+ argString = argString.arg( TimeStringFormat::tr("AM") );
return argString;
}
QString TimeString::shortTime( bool ampm, bool seconds )
{
- static const char* const day[] = {
- QT_TRANSLATE_NOOP( "QObject", "Mon" ),
- QT_TRANSLATE_NOOP( "QObject", "Tue" ),
- QT_TRANSLATE_NOOP( "QObject", "Wed" ),
- QT_TRANSLATE_NOOP( "QObject", "Thu" ),
- QT_TRANSLATE_NOOP( "QObject", "Fri" ),
- QT_TRANSLATE_NOOP( "QObject", "Sat" ),
- QT_TRANSLATE_NOOP( "QObject", "Sun" )
- };
// just create a shorter time String
QDateTime dtTmp = QDateTime::currentDateTime();
- QString strTime;
- strTime = QObject::tr( day[dtTmp.date().dayOfWeek()-1] ) + " " +
- timeString( dtTmp.time(), ampm, seconds );
+ QString strTime = TimeStringFormat::tr( "%1 %2", "1=Monday 2=12:45" )
+ .arg(::dayname(dtTmp.date(),FALSE))
+ .arg(timeString( dtTmp.time(), ampm, seconds ));
return strTime;
}
QString TimeString::dateString( const QDateTime &t, bool ampm )
{
return dateString(t,ampm,FALSE);
}
QString TimeString::timeString( const QTime &t, bool ampm)
{
return timeString(t,ampm,FALSE);
}
QString TimeString::shortTime( bool ampm )
{
return shortTime(ampm,FALSE);
}
QString TimeString::numberDateString( const QDate &d, DateFormat dtf )
{
return dtf.numberDate(d);
}
QString TimeString::longNumberDateString( const QDate &d, DateFormat dtf )
{
return dtf.numberDate(d,DateFormat::longNumber);
}
+/*!
+ Returns date/time \a dt as a string,
+ showing year, month, date, hours, minutes, and seconds.
+ \a len determines the length of the resulting string.
+
+ The format, including order depends on the user's settings.
+
+ First availability: Qtopia 1.6
+*/
+//QString TimeString::localYMDHMS( const QDateTime &dt, Length len )
+//{
+// const QDate& d = dt.date();
+// const QTime& t = dt.time();
+// return LocalTimeFormat::tr("%1 %2","date,time").arg(localYMD(d,len)).arg(localHMS(t));
+//}
+
#include "timestring.moc"
diff --git a/library/timestring.h b/library/timestring.h
index 875c8bf..b8d1aea 100644
--- a/library/timestring.h
+++ b/library/timestring.h
@@ -1,150 +1,182 @@
/**********************************************************************
-** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
**
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file.
-**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
-** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef _TIMESTRING_H_
#define _TIMESTRING_H_
#include <qdatetime.h>
#include <qstring.h>
+#include <qarray.h>
#if (QT_VERSION-0 >= 0x030000)
#define DateFormat QPEDateFormat
#endif
+#include <qtopia/qpeglobal.h>
+
+class QObject;
+
// return a string with the time based on whether or not you want
// you want it in 12 hour form. if ampm is true, then return
// it in 12 hour (am/pm) form otherwise return it in 24 hour form
// in theory Qt 3,0 handles this better (hopefully obsoleteing this)
-class DateFormat
+class DateFormat
{
public:
- // date format type 001,010,100 = day month year
+ // date format type 1,2,4 = day,month,year
enum Order {
- DayMonthYear = 0x0111, // 0x001 + 0x010(0x2 << 3) + 0x100(0x4 << 3)
- MonthDayYear = 0x010A,
- YearMonthDay = 0x0054
+ DayMonthYear = 0421, // right-to-left
+ MonthDayYear = 0412,
+ YearMonthDay = 0124
};
DateFormat(QChar s = '/', Order so = MonthDayYear) : _shortOrder(so),
_longOrder(so), _shortSeparator(s) { }
DateFormat(QChar s, Order so, Order lo) : _shortOrder(so),
_longOrder(lo), _shortSeparator(s) { }
DateFormat(const DateFormat &o) : _shortOrder(o._shortOrder),
_longOrder(o._longOrder), _shortSeparator(o._shortSeparator) { }
bool operator==(const DateFormat &o)
{
if (o._shortOrder == _shortOrder && o._longOrder == _longOrder &&
o._shortSeparator == _shortSeparator)
return TRUE;
return FALSE;
}
// verbosity specifiers
enum Verbosity {
shortNumber = 0x01, // default
longNumber = 0x02,
padNumber = 0x04,
shortWord = 0x08, // default
longWord = 0x10,
showWeekDay = 0x20
};
QString toNumberString() const; // the M/D/Y string.
QString toWordString() const; // the Month day, year string.
QString numberDate(const QDate &d, int v = 0) const;
QString wordDate(const QDate &d, int v = 0) const;
#ifndef QT_NO_DATASTREAM
void load(QDataStream&);
void save(QDataStream&) const;
#endif
QChar separator() const { return _shortSeparator; };
Order shortOrder() const { return _shortOrder; };
Order longOrder() const { return _longOrder; };
private:
Order _shortOrder;
Order _longOrder;
QChar _shortSeparator;
};
#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &s, const DateFormat&df);
QDataStream &operator>>(QDataStream &s, DateFormat&df);
#endif
class TimeString
{
public:
- //enum DateFormat { MonthDayYear, DayMonthYear, ISO8601,
+ //enum DateFormat { MonthDayYear, DayMonthYear, ISO8601,
//YearMonthDay = ISO8601 };
-/**
- * @name Convience functions which use currentDateFormat
- */
-//@{
- static QString shortDate( const QDate &d )
+
+//private:
+ static QString shortDate( const QDate &d )
{ return shortDate( d, currentDateFormat() ); }
static QString dateString( const QDate &d )
{ return dateString( d, currentDateFormat() ); }
static QString longDateString( const QDate &d )
{ return longDateString( d, currentDateFormat() ); }
-//@}
static QString dateString( const QDateTime &dt, bool ampm, bool seconds )
{ return dateString( dt, ampm, seconds, currentDateFormat() ); }
+public:
+ enum Length { Short, Medium, Long };
+ static QString localH( int hour );
+ static QString localHM( const QTime & );
+ static QString localHM( const QTime &, Length ); // qtopia 2.1.0
+ static QString localHMS( const QTime & );
+ static QString localHMDayOfWeek( const QDateTime &t );
+ static QString localHMSDayOfWeek( const QDateTime &t );
+ static QString localMD( const QDate &, Length=Medium );
+ static QString localYMD( const QDate &, Length=Medium );
+ static QString localYMDHMS( const QDateTime &, Length=Medium );
+ static QString localDayOfWeek( const QDate&, Length=Medium );
+ static QString localDayOfWeek( int day1to7, Length=Medium );
+
+ static QString hourString( int hour, bool ampm );
+ static bool currentAMPM();
+ static DateFormat currentDateFormat();
+ static QArray<DateFormat> formatOptions(); // qtopia 1.6.0
+
+ static void connectChange(QObject*,const char* member);
+ static void disconnectChange(QObject*,const char* member);
- /** @name Do not use as they don't honor system settings for AMPM
- *
- */
- //@{
- static QString dateString( const QDateTime &t, bool ampm = false );
+ // Not recommended to call these (they don't honor system ampm)
+ static QString dateString( const QDateTime &t, bool ampm );
static QString timeString( const QTime &t, bool ampm, bool seconds );
- static QString timeString( const QTime &t, bool ampm = false );
+ static QString timeString( const QTime &t, bool ampm );
static QString shortTime( bool ampm, bool seconds );
- static QString shortTime( bool ampm = false );
- //@}
+ static QString shortTime( bool ampm );
static QString numberDateString( const QDate &d, DateFormat );
static QString numberDateString( const QDate &d )
{ return numberDateString( d, currentDateFormat() ); }
static QString longNumberDateString( const QDate &d, DateFormat );
static QString longNumberDateString( const QDate &d )
{ return longNumberDateString( d, currentDateFormat() ); }
static QString shortDate( const QDate &, DateFormat );
static QString dateString( const QDate &, DateFormat );
static QString longDateString( const QDate &, DateFormat );
- static DateFormat currentDateFormat();
-
private:
static QString dateString( const QDateTime &t, bool ampm, bool seconds, DateFormat );
-
+
};
#endif
diff --git a/noncore/multimedia/camera2/camera2.pro b/noncore/multimedia/camera2/camera2.pro
new file mode 100644
index 0000000..b6e2826
--- a/dev/null
+++ b/noncore/multimedia/camera2/camera2.pro
@@ -0,0 +1,27 @@
+DESTDIR = $(OPIEDIR)/bin
+TEMPLATE = app
+CONFIG += qte warn_on quick_app
+INTERFACES=camerabase.ui camerasettings.ui
+HEADERS = mainwindow.h \
+ image.h \
+ thumbbutton.h \
+ videocaptureview.h
+SOURCES = mainwindow.cpp\
+ image.cpp \
+ videocaptureview.cpp \
+ main.cpp
+
+TARGET = camera2
+DEFINES += HAVE_VIDEO4LINUX
+
+LIBS += -lopiecore2 -lopieui2
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+contains(CONFIG,quick-app) {
+ DESTDIR = $(OPIEDIR)/bin
+ DEFINES += NOQUICKLAUNCH
+}
+
+
+include( $(OPIEDIR)/include.pro )
+
diff --git a/noncore/multimedia/camera2/camerabase.cpp b/noncore/multimedia/camera2/camerabase.cpp
new file mode 100644
index 0000000..cbb1ba9
--- a/dev/null
+++ b/noncore/multimedia/camera2/camerabase.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+** Form implementation generated from reading ui file 'camerabase.ui'
+**
+** Created: Mon Jul 10 04:21:25 2006
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#include "camerabase.h"
+
+#include <qframe.h>
+#include <qpushbutton.h>
+#include "thumbbutton.h"
+#include "videocaptureview.h"
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+/*
+ * Constructs a CameraBase which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ */
+CameraBase::CameraBase( QWidget* parent, const char* name, WFlags fl )
+ : QWidget( parent, name, fl )
+{
+ if ( !name )
+ setName( "camera" );
+ resize( 311, 381 );
+ setCaption( tr( "Camera" ) );
+ cameraLayout = new QGridLayout( this );
+ cameraLayout->setSpacing( 0 );
+ cameraLayout->setMargin( 0 );
+
+ Frame3 = new QFrame( this, "Frame3" );
+ Frame3->setFrameShape( QFrame::Panel );
+ Frame3->setFrameShadow( QFrame::Sunken );
+ Frame3->setLineWidth( 4 );
+ Frame3->setMargin( 4 );
+ Frame3->setMidLineWidth( 3 );
+ Frame3Layout = new QVBoxLayout( Frame3 );
+ Frame3Layout->setSpacing( 6 );
+ Frame3Layout->setMargin( 4 );
+
+ videocaptureview = new VideoCaptureView( Frame3, "videocaptureview" );
+ videocaptureview->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, videocaptureview->sizePolicy().hasHeightForWidth() ) );
+ Frame3Layout->addWidget( videocaptureview );
+
+ cameraLayout->addMultiCellWidget( Frame3, 0, 0, 0, 1 );
+
+ photo = new QPushButton( this, "photo" );
+ photo->setText( tr( "Photo" ) );
+
+ cameraLayout->addWidget( photo, 1, 0 );
+
+ video = new QPushButton( this, "video" );
+ video->setText( tr( "Video" ) );
+
+ cameraLayout->addWidget( video, 1, 1 );
+
+ thumbs = new QFrame( this, "thumbs" );
+ thumbs->setFrameShape( QFrame::NoFrame );
+ thumbs->setFrameShadow( QFrame::Plain );
+ thumbsLayout = new QHBoxLayout( thumbs );
+ thumbsLayout->setSpacing( 0 );
+ thumbsLayout->setMargin( 0 );
+
+ thumb1 = new ThumbButton( thumbs, "thumb1" );
+ thumbsLayout->addWidget( thumb1 );
+
+ thumb2 = new ThumbButton( thumbs, "thumb2" );
+ thumbsLayout->addWidget( thumb2 );
+
+ thumb3 = new ThumbButton( thumbs, "thumb3" );
+ thumbsLayout->addWidget( thumb3 );
+
+ thumb4 = new ThumbButton( thumbs, "thumb4" );
+ thumbsLayout->addWidget( thumb4 );
+
+ thumb5 = new ThumbButton( thumbs, "thumb5" );
+ thumbsLayout->addWidget( thumb5 );
+
+ cameraLayout->addMultiCellWidget( thumbs, 2, 2, 0, 1 );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+CameraBase::~CameraBase()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
diff --git a/noncore/multimedia/camera2/camerabase.h b/noncore/multimedia/camera2/camerabase.h
new file mode 100644
index 0000000..77ab4f0
--- a/dev/null
+++ b/noncore/multimedia/camera2/camerabase.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+** Form interface generated from reading ui file 'camerabase.ui'
+**
+** Created: Mon Jul 10 04:21:22 2006
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <qvariant.h>
+#include <qwidget.h>
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QFrame;
+class QPushButton;
+class ThumbButton;
+class VideoCaptureView;
+
+class CameraBase : public QWidget
+{
+ Q_OBJECT
+
+public:
+ CameraBase( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~CameraBase();
+
+ QFrame* Frame3;
+ VideoCaptureView* videocaptureview;
+ QPushButton* photo;
+ QPushButton* video;
+ QFrame* thumbs;
+ ThumbButton* thumb1;
+ ThumbButton* thumb2;
+ ThumbButton* thumb3;
+ ThumbButton* thumb4;
+ ThumbButton* thumb5;
+
+protected:
+ QGridLayout* cameraLayout;
+ QVBoxLayout* Frame3Layout;
+ QHBoxLayout* thumbsLayout;
+};
+
+#endif // CAMERA_H
diff --git a/noncore/multimedia/camera2/camerabase.ui b/noncore/multimedia/camera2/camerabase.ui
new file mode 100644
index 0000000..e102f79
--- a/dev/null
+++ b/noncore/multimedia/camera2/camerabase.ui
@@ -0,0 +1,209 @@
+<!DOCTYPE UI><UI>
+<class>CameraBase</class>
+<widget>
+ <class>QWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>camera</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>311</width>
+ <height>381</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>Camera</string>
+ </property>
+ <grid>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>0</number>
+ </property>
+ <widget row="0" column="0" rowspan="1" colspan="2" >
+ <class>QFrame</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Frame3</cstring>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>Panel</enum>
+ </property>
+ <property stdset="1">
+ <name>frameShadow</name>
+ <enum>Sunken</enum>
+ </property>
+ <property stdset="1">
+ <name>lineWidth</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>margin</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>midLineWidth</name>
+ <number>3</number>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>VideoCaptureView</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>videocaptureview</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget row="1" column="0" >
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>photo</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Photo</string>
+ </property>
+ </widget>
+ <widget row="1" column="1" >
+ <class>QPushButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>video</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Video</string>
+ </property>
+ </widget>
+ <widget row="2" column="0" rowspan="1" colspan="2" >
+ <class>QFrame</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>thumbs</cstring>
+ </property>
+ <property stdset="1">
+ <name>frameShape</name>
+ <enum>NoFrame</enum>
+ </property>
+ <property stdset="1">
+ <name>frameShadow</name>
+ <enum>Plain</enum>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>0</number>
+ </property>
+ <widget>
+ <class>ThumbButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>thumb1</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>ThumbButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>thumb2</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>ThumbButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>thumb3</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>ThumbButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>thumb4</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>ThumbButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>thumb5</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>VideoCaptureView</class>
+ <header location="local">videocaptureview.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>7</hordata>
+ <verdata>7</verdata>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>ThumbButton</class>
+ <header location="local">thumbbutton.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ </sizepolicy>
+ <pixmap>image1</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image>
+ <name>image0</name>
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+ <image>
+ <name>image1</name>
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1ddec44f503c0ae2a154410f53d0ed20e2bf6bdb656dd6861dd23d9a66591b0587fd1654235ebded6f0edcd53e419d87ae7b1f4f9b8f906d0bfe012317426a70b07bdc2f3ec77f8ed6b89559061a0343d06a124cc105596482585094bc0ae599b04646c9018926491b2205e140c485cace25755c175d0a967b622ff900b8cc9c7d29af594ea722d589167f813aa852ba07d94b9dce296e883fe7bb163f23896753</data>
+ </image>
+</images>
+</UI>
diff --git a/noncore/multimedia/camera2/camerasettings.cpp b/noncore/multimedia/camera2/camerasettings.cpp
new file mode 100644
index 0000000..d284128
--- a/dev/null
+++ b/noncore/multimedia/camera2/camerasettings.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+** Form implementation generated from reading ui file 'camerasettings.ui'
+**
+** Created: Mon Jul 10 04:21:25 2006
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#include "camerasettings.h"
+
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qslider.h>
+#include <qtopia/locationcombo.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+/*
+ * Constructs a CameraSettings which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+CameraSettings::CameraSettings( QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl )
+{
+ if ( !name )
+ setName( "CameraSettings" );
+ resize( 324, 465 );
+ setCaption( tr( "Settings" ) );
+ CameraSettingsLayout = new QVBoxLayout( this );
+ CameraSettingsLayout->setSpacing( 6 );
+ CameraSettingsLayout->setMargin( 11 );
+
+ location = new LocationCombo( this, "location" );
+ CameraSettingsLayout->addWidget( location );
+
+ photo = new QGroupBox( this, "photo" );
+ photo->setTitle( tr( "Photo" ) );
+ photo->setColumnLayout(0, Qt::Vertical );
+ photo->layout()->setSpacing( 0 );
+ photo->layout()->setMargin( 0 );
+ photoLayout = new QVBoxLayout( photo->layout() );
+ photoLayout->setAlignment( Qt::AlignTop );
+ photoLayout->setSpacing( 2 );
+ photoLayout->setMargin( 4 );
+
+ Layout1 = new QHBoxLayout;
+ Layout1->setSpacing( 6 );
+ Layout1->setMargin( 0 );
+
+ TextLabel1 = new QLabel( photo, "TextLabel1" );
+ TextLabel1->setText( tr( "Size" ) );
+ Layout1->addWidget( TextLabel1 );
+
+ photo_size = new QComboBox( FALSE, photo, "photo_size" );
+ photo_size->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, photo_size->sizePolicy().hasHeightForWidth() ) );
+ Layout1->addWidget( photo_size );
+ photoLayout->addLayout( Layout1 );
+
+ Layout2 = new QHBoxLayout;
+ Layout2->setSpacing( 6 );
+ Layout2->setMargin( 0 );
+
+ TextLabel2 = new QLabel( photo, "TextLabel2" );
+ TextLabel2->setText( tr( "Quality" ) );
+ Layout2->addWidget( TextLabel2 );
+
+ photo_quality = new QSlider( photo, "photo_quality" );
+ photo_quality->setMinValue( 0 );
+ photo_quality->setMaxValue( 100 );
+ photo_quality->setValue( 75 );
+ photo_quality->setOrientation( QSlider::Horizontal );
+ Layout2->addWidget( photo_quality );
+
+ photo_quality_n = new QLabel( photo, "photo_quality_n" );
+ photo_quality_n->setText( tr( "75" ) );
+ Layout2->addWidget( photo_quality_n );
+ photoLayout->addLayout( Layout2 );
+ CameraSettingsLayout->addWidget( photo );
+
+ video = new QGroupBox( this, "video" );
+ video->setTitle( tr( "Video" ) );
+ video->setColumnLayout(0, Qt::Vertical );
+ video->layout()->setSpacing( 0 );
+ video->layout()->setMargin( 0 );
+ videoLayout = new QVBoxLayout( video->layout() );
+ videoLayout->setAlignment( Qt::AlignTop );
+ videoLayout->setSpacing( 2 );
+ videoLayout->setMargin( 4 );
+
+ Layout1_2 = new QHBoxLayout;
+ Layout1_2->setSpacing( 6 );
+ Layout1_2->setMargin( 0 );
+
+ TextLabel1_2 = new QLabel( video, "TextLabel1_2" );
+ TextLabel1_2->setText( tr( "Size" ) );
+ Layout1_2->addWidget( TextLabel1_2 );
+
+ video_size = new QComboBox( FALSE, video, "video_size" );
+ video_size->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, video_size->sizePolicy().hasHeightForWidth() ) );
+ Layout1_2->addWidget( video_size );
+ videoLayout->addLayout( Layout1_2 );
+
+ Layout2_2 = new QHBoxLayout;
+ Layout2_2->setSpacing( 6 );
+ Layout2_2->setMargin( 0 );
+
+ TextLabel2_2 = new QLabel( video, "TextLabel2_2" );
+ TextLabel2_2->setText( tr( "Quality" ) );
+ Layout2_2->addWidget( TextLabel2_2 );
+
+ video_quality = new QSlider( video, "video_quality" );
+ video_quality->setMinValue( 0 );
+ video_quality->setMaxValue( 100 );
+ video_quality->setValue( 75 );
+ video_quality->setOrientation( QSlider::Horizontal );
+ Layout2_2->addWidget( video_quality );
+
+ video_quality_n = new QLabel( video, "video_quality_n" );
+ video_quality_n->setText( tr( "75" ) );
+ Layout2_2->addWidget( video_quality_n );
+ videoLayout->addLayout( Layout2_2 );
+
+ Layout6 = new QHBoxLayout;
+ Layout6->setSpacing( 6 );
+ Layout6->setMargin( 0 );
+
+ TextLabel4 = new QLabel( video, "TextLabel4" );
+ TextLabel4->setText( tr( "Frame rate" ) );
+ Layout6->addWidget( TextLabel4 );
+
+ video_framerate = new QSlider( video, "video_framerate" );
+ video_framerate->setMinValue( 1 );
+ video_framerate->setMaxValue( 60 );
+ video_framerate->setValue( 5 );
+ video_framerate->setOrientation( QSlider::Horizontal );
+ Layout6->addWidget( video_framerate );
+
+ TextLabel6 = new QLabel( video, "TextLabel6" );
+ TextLabel6->setText( tr( "5" ) );
+ Layout6->addWidget( TextLabel6 );
+ videoLayout->addLayout( Layout6 );
+ CameraSettingsLayout->addWidget( video );
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ CameraSettingsLayout->addItem( spacer );
+
+ // signals and slots connections
+ connect( photo_quality, SIGNAL( valueChanged(int) ), photo_quality_n, SLOT( setNum(int) ) );
+ connect( video_quality, SIGNAL( valueChanged(int) ), video_quality_n, SLOT( setNum(int) ) );
+ connect( video_framerate, SIGNAL( valueChanged(int) ), TextLabel6, SLOT( setNum(int) ) );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+CameraSettings::~CameraSettings()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
diff --git a/noncore/multimedia/camera2/camerasettings.h b/noncore/multimedia/camera2/camerasettings.h
new file mode 100644
index 0000000..dcc48a0
--- a/dev/null
+++ b/noncore/multimedia/camera2/camerasettings.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+** Form interface generated from reading ui file 'camerasettings.ui'
+**
+** Created: Mon Jul 10 04:21:22 2006
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#ifndef CAMERASETTINGS_H
+#define CAMERASETTINGS_H
+
+#include <qvariant.h>
+#include <qdialog.h>
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class LocationCombo;
+class QComboBox;
+class QGroupBox;
+class QLabel;
+class QSlider;
+
+class CameraSettings : public QDialog
+{
+ Q_OBJECT
+
+public:
+ CameraSettings( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+ ~CameraSettings();
+
+ LocationCombo* location;
+ QGroupBox* photo;
+ QLabel* TextLabel1;
+ QComboBox* photo_size;
+ QLabel* TextLabel2;
+ QSlider* photo_quality;
+ QLabel* photo_quality_n;
+ QGroupBox* video;
+ QLabel* TextLabel1_2;
+ QComboBox* video_size;
+ QLabel* TextLabel2_2;
+ QSlider* video_quality;
+ QLabel* video_quality_n;
+ QLabel* TextLabel4;
+ QSlider* video_framerate;
+ QLabel* TextLabel6;
+
+protected:
+ QVBoxLayout* CameraSettingsLayout;
+ QVBoxLayout* photoLayout;
+ QHBoxLayout* Layout1;
+ QHBoxLayout* Layout2;
+ QVBoxLayout* videoLayout;
+ QHBoxLayout* Layout1_2;
+ QHBoxLayout* Layout2_2;
+ QHBoxLayout* Layout6;
+};
+
+#endif // CAMERASETTINGS_H
diff --git a/noncore/multimedia/camera2/camerasettings.ui b/noncore/multimedia/camera2/camerasettings.ui
new file mode 100644
index 0000000..276694b
--- a/dev/null
+++ b/noncore/multimedia/camera2/camerasettings.ui
@@ -0,0 +1,433 @@
+<!DOCTYPE UI><UI>
+<class>CameraSettings</class>
+<widget>
+ <class>QDialog</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>CameraSettings</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>324</width>
+ <height>465</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>Settings</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>LocationCombo</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>location</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>photo</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Photo</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>2</number>
+ </property>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Size</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>photo_size</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout2</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Quality</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QSlider</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>photo_quality</cstring>
+ </property>
+ <property stdset="1">
+ <name>minValue</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>maxValue</name>
+ <number>100</number>
+ </property>
+ <property stdset="1">
+ <name>value</name>
+ <number>75</number>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>photo_quality_n</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>75</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>video</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Video</string>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>2</number>
+ </property>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout1_2</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Size</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QComboBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>video_size</cstring>
+ </property>
+ <property stdset="1">
+ <name>sizePolicy</name>
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout2_2</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Quality</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QSlider</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>video_quality</cstring>
+ </property>
+ <property stdset="1">
+ <name>minValue</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>maxValue</name>
+ <number>100</number>
+ </property>
+ <property stdset="1">
+ <name>value</name>
+ <number>75</number>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>video_quality_n</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>75</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout6</cstring>
+ </property>
+ <hbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Frame rate</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QSlider</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>video_framerate</cstring>
+ </property>
+ <property stdset="1">
+ <name>minValue</name>
+ <number>1</number>
+ </property>
+ <property stdset="1">
+ <name>maxValue</name>
+ <number>60</number>
+ </property>
+ <property stdset="1">
+ <name>value</name>
+ <number>5</number>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel6</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>5</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer1</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>LocationCombo</class>
+ <header location="global">qtopia/locationcombo.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image>
+ <name>image0</name>
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>photo_quality</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>photo_quality_n</receiver>
+ <slot>setNum(int)</slot>
+ </connection>
+ <connection>
+ <sender>video_quality</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>video_quality_n</receiver>
+ <slot>setNum(int)</slot>
+ </connection>
+ <connection>
+ <sender>video_framerate</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>TextLabel6</receiver>
+ <slot>setNum(int)</slot>
+ </connection>
+</connections>
+</UI>
diff --git a/noncore/multimedia/camera2/config.in b/noncore/multimedia/camera2/config.in
new file mode 100644
index 0000000..8838008
--- a/dev/null
+++ b/noncore/multimedia/camera2/config.in
@@ -0,0 +1,7 @@
+ config CAMERA2
+ boolean "opie-camera2 (camera app to use with Video4Linux)"
+ default "n"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2UI
+ comment "opie-camera needs a libqpe, libopie2core & libopie2ui"
+ depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2UI )
+
diff --git a/noncore/multimedia/camera2/image.cpp b/noncore/multimedia/camera2/image.cpp
new file mode 100644
index 0000000..39b6d8b
--- a/dev/null
+++ b/noncore/multimedia/camera2/image.cpp
@@ -0,0 +1,239 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "image.h"
+
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qstring.h>
+
+/*!
+ Returns an image created by loading the \a filename,
+ and scalining it, preserving aspect ratio, to fit in
+ \a width by \a height pixels.
+
+ First availability: Qtopia 2.0
+*/
+QImage Image::loadScaled(const QString & filename, const int width, const int height,
+ ScaleMode mode)
+{
+ QImageIO iio;
+ QString param;
+ int w = width;
+ int h = height;
+
+ if (width == 0 || height == 0)
+ return QImage();
+
+ iio.setFileName(filename);
+
+ //
+ // Try and load and scale the image in one hit.
+ //
+ param.sprintf("GetHeaderInformation");
+ iio.setParameters(param);
+ iio.read();
+
+ //
+ // If we don't have bits(), read() understands parameters,
+ // and we can setup for fast reading. Otherwise, take the
+ // performance hit and do things slowly.
+ //
+ if (!iio.image().bits()) {
+ if ((iio.image().width() < w) && (iio.image().height() < h)) {
+ param.sprintf("%s", "Fast"); // No Tr
+ }
+ else {
+ int shrink_factor = 1;
+ QString smode;
+ switch (mode) {
+ case ScaleMin:
+ smode = "ScaleMin";
+ shrink_factor = QMAX(iio.image().width() / w, iio.image().height() / h);
+ break;
+ case ScaleMax:
+ smode = "ScaleMax";
+ shrink_factor = QMIN(iio.image().width() / w, iio.image().height() / h);
+ break;
+ case ScaleFree:
+ smode = "ScaleFree";
+ shrink_factor = QMIN(iio.image().width() / w, iio.image().height() / h);
+ break;
+ }
+ param.sprintf("Scale( %i, %i, %s )%s, Shrink( %i )", // No tr
+ w, h, smode.latin1(), ", Fast", shrink_factor); // No tr
+ }
+
+ iio.setParameters(param);
+ iio.read();
+ return iio.image();
+ }
+
+ if ((iio.image().width() > w) || (iio.image().height() > h)) {
+ QSize s = aspectScaleSize(iio.image().width(), iio.image().height(), w, h, mode);
+ return iio.image().smoothScale(s.width(), s.height());
+ }
+
+ return iio.image();
+}
+
+//
+// Returns new size of image, scaled to target_width and target_height,
+// whilst preserving aspect ratio. Useful when it's not possible to
+// scale an image prior to using it (eg. using RichText). Should be in
+// global image utils.
+//
+// NOTE
+// - expensive for images whose drivers do not allow us to retrieve
+// parameters without reading the entire image. Currently (20030930)
+// only the jpeg driver allows parameter reading.
+//
+QSize Image::loadScaledImageSize(const QString & filename, int target_width, int target_height,
+ int maxscale, ScaleMode mode)
+{
+ QImageIO iio;
+ iio.setFileName(filename);
+ iio.setParameters("GetHeaderInformation");
+ iio.read();
+
+ int w = iio.image().width();
+ int h = iio.image().height();
+
+ //
+ // Scaling up small pictures can be very ugly.
+ // Leave them alone if they are too small.
+ //
+ if (maxscale && w * maxscale < target_width && h * maxscale < target_height)
+ return QSize(w * maxscale, h * maxscale);
+
+ return aspectScaleSize(w, h, target_width, target_height, mode);
+}
+
+// Load an image to be used as a portrait. Force its height to height,
+// scale width to new height, and crop the width if it's still > width
+// XXX : Should be using integer math
+QImage Image::loadPortrait(const QString & filename, const int width, const int height)
+{
+ QImageIO iio;
+ QString param;
+ int w = width;
+ int h = height;
+
+ if (width == 0 || height == 0)
+ return QImage();
+
+ iio.setFileName(filename);
+
+ //
+ // Try and load and scale the image in one hit.
+ //
+ param.sprintf("GetHeaderInformation");
+ iio.setParameters(param);
+ iio.read();
+
+ //
+ // If we don't have bits(), read() understands parameters,
+ // and we can setup for fast reading. Otherwise, take the
+ // performance hit and do things slowly.
+ //
+ if (!iio.image().bits()) {
+
+ w = (int) ((double) iio.image().width() / (double) (iio.image().height()) *
+ (double) height);
+ param.sprintf("Scale( %i, %i, ScaleFree )%s", // No tr
+ w, h, ", Fast"); // No tr
+
+ iio.setParameters(param);
+ iio.read();
+
+ if (w > width) {
+ int x = (int) ((double) (w - width) / 2);
+ QRect r(x, 0, width, height);
+ return iio.image().copy(r);
+ }
+ else
+ return iio.image();
+ }
+ else
+ //scale width to the new height
+ return sizeToPortrait(iio.image(), width, height);
+}
+
+QImage Image::sizeToPortrait(const QImage & image, const int width, const int height)
+{
+ int w = (image.width() * height) / image.height();
+ if (w > width) {
+ int x = (w - width) / 2;
+ QRect r(x, 0, width, height);
+ return image.smoothScale(w, height).copy(r);
+ }
+ else
+ return image.smoothScale(width, height);
+}
+
+//
+// Return (w x h) scaled to (target_width x target_height) with aspect
+// ratio preserved.
+//
+QSize
+ Image::aspectScaleSize(const int w, const int h, const int target_width,
+ const int target_height, ScaleMode mode)
+{
+ QSize s;
+ if (mode == ScaleFree) {
+ s = QSize(target_width, target_height);
+ }
+ else {
+ bool useHeight = TRUE;
+ int rw = target_height * w / h;
+
+ if (mode == ScaleMin) {
+ useHeight = (rw <= target_width);
+ }
+ else { // mode == ScaleMax
+ useHeight = (rw >= target_width);
+ }
+
+ if (useHeight) {
+ s = QSize(rw, target_height);
+ }
+ else {
+ s = QSize(target_width, target_width * h / w);
+ }
+ }
+
+ return s;
+}
+
diff --git a/noncore/multimedia/camera2/image.h b/noncore/multimedia/camera2/image.h
new file mode 100644
index 0000000..36394ff
--- a/dev/null
+++ b/noncore/multimedia/camera2/image.h
@@ -0,0 +1,53 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include <qimage.h>
+#include <qtopia/qpeglobal.h>
+
+class Image {
+public:
+ // namespace
+ enum ScaleMode { ScaleFree, ScaleMin, ScaleMax };
+ static QImage loadScaled(const QString &filename, const int width, const int height, ScaleMode mode=ScaleMin);
+ static QSize loadScaledImageSize(const QString &filename, int target_width, int target_height, int maxscale=1, ScaleMode mode=ScaleMin);
+ static QImage loadPortrait(const QString &filename, const int width, const int height);
+ static QImage sizeToPortrait(const QImage &image, const int width, const int height);
+ static QSize aspectScaleSize(const int w, const int h, const int target_width, const int target_height, ScaleMode mode=ScaleMin);
+};
+
+#endif // IMAGE_H
diff --git a/noncore/multimedia/camera2/main.cpp b/noncore/multimedia/camera2/main.cpp
new file mode 100644
index 0000000..00e21de
--- a/dev/null
+++ b/noncore/multimedia/camera2/main.cpp
@@ -0,0 +1,44 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "mainwindow.h"
+#include <opie2/oapplication.h>
+#include <opie2/oapplicationfactory.h>
+
+using namespace Opie::Core;
+OPIE_EXPORT_APP(OApplicationFactory < CameraMainWindow >)
+// QTOPIA_ADD_APPLICATION("camera",CameraMainWindow)
+// QTOPIA_MAIN
+
diff --git a/noncore/multimedia/camera2/mainwindow.cpp b/noncore/multimedia/camera2/mainwindow.cpp
new file mode 100644
index 0000000..45f8cdf
--- a/dev/null
+++ b/noncore/multimedia/camera2/mainwindow.cpp
@@ -0,0 +1,763 @@
+/**********************************************************************
+ ** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+ **
+ ** This file is part of the Qtopia Environment.
+ **
+ ** This program is free software; you can redistribute it and/or modify it
+ ** under the terms of the GNU General Public License as published by the
+ ** Free Software Foundation; either version 2 of the License, or (at your
+ ** option) any later version.
+ **
+ ** A copy of the GNU GPL license version 2 is included in this package as
+ ** LICENSE.GPL.
+ **
+ ** This program is distributed in the hope that it will be useful, but
+ ** WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ ** See the GNU General Public License for more details.
+ **
+ ** In addition, as a special exception Trolltech gives permission to link
+ ** the code of this program with Qtopia applications copyrighted, developed
+ ** and distributed by Trolltech under the terms of the Qtopia Personal Use
+ ** License Agreement. You must comply with the GNU General Public License
+ ** in all respects for all of the code used other than the applications
+ ** licensed under the Qtopia Personal Use License Agreement. If you modify
+ ** this file, you may extend this exception to your version of the file,
+ ** but you are not obligated to do so. If you do not wish to do so, delete
+ ** this exception statement from your version.
+ **
+ ** See http://www.trolltech.com/gpl/ for GPL licensing information.
+ **
+ ** Contact info@trolltech.com if any conditions of this licensing are
+ ** not clear to you.
+ **
+ **********************************************************************/
+
+#define QTOPIA_INTERNAL_FILEOPERATIONS
+#include "mainwindow.h"
+#include "videocaptureview.h"
+#include "camerasettings.h"
+#include "thumbbutton.h"
+
+#include "image.h"
+
+/* OPIE */
+#include <opie2/odebug.h>
+#include <opie2/oresource.h>
+using namespace Opie::Core;
+
+#include <qpe/config.h>
+#include <qpe/qpeapplication.h>
+#include <qpe/locationcombo.h>
+//#include <qtopia/contextmenu.h>
+#include <qpe/qcopenvelope_qws.h>
+#include <qpe/resource.h>
+//#include <qtopia/services.h>
+#include <qpe/categories.h>
+#include <qpe/qpetoolbar.h>
+#include <qpe/global.h>
+
+#include <qaction.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <qpushbutton.h>
+#include <qgroupbox.h>
+#include <qsignalmapper.h>
+#include <qdir.h>
+#include <qimage.h>
+#include <qslider.h>
+#include <qtimer.h>
+#include <qmessagebox.h>
+
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static const int thmarg = 2;
+static const bool video_supported = FALSE;
+
+CameraMainWindow::CameraMainWindow(QWidget * parent, const char *name, WFlags f)
+:QMainWindow(parent, name, f)
+{
+ setCaption(tr("Camera"));
+
+ picfile = Global::tempDir() + "image.jpg";
+ camera = new CameraBase(this);
+ setCentralWidget(camera);
+
+ connect(qApp, SIGNAL(appMessage(const QCString &, const QByteArray &)),
+ this, SLOT(appMessage(const QCString &, const QByteArray &)));
+ connect(qApp, SIGNAL(linkChanged(const QString &)), this, SLOT(linkChanged(const QString &)));
+
+ Categories cats;
+ cats.load(categoryFileName());
+ camcat = cats.id("Document View", "_Camera"); // No tr
+ if (!camcat) {
+ camcat = cats.addCategory("Document View", "_Camera"); // No tr
+ cats.save(categoryFileName());
+ }
+
+ camera->photo->setFocus();
+
+ connect(camera->photo, SIGNAL(clicked()), this, SLOT(takePhoto()));
+ connect(camera->video, SIGNAL(clicked()), this, SLOT(toggleVideo()));
+
+ refocusTimer = new QTimer(this);
+ connect(refocusTimer, SIGNAL(timeout()), this, SLOT(takePhotoNow()));
+
+ thumb[0] = camera->thumb1;
+ thumb[1] = camera->thumb2;
+ thumb[2] = camera->thumb3;
+ thumb[3] = camera->thumb4;
+ thumb[4] = camera->thumb5;
+ cur_thumb = -1;
+
+ QSignalMapper *sm = new QSignalMapper(this);
+ for (int i = 0; i < nthumb; i++) {
+ sm->setMapping(thumb[i], i);
+ connect(thumb[i], SIGNAL(clicked()), sm, SLOT(map()));
+ thumb[i]->installEventFilter(this);
+ }
+ connect(sm, SIGNAL(mapped(int)), this, SLOT(thumbClicked(int)));
+
+#warning fixme
+// AppLnk picture_viewer = Service::appLnk("PhotoEdit");
+// AppLnk video_viewer = Service::appLnk("Open/video/mpeg");
+
+ a_pview = new QAction(tr("%1...", "app name").arg("" /*picture_viewer.name() */ ),
+ Resource::loadPixmap(NULL /*picture_viewer.icon() */ ), QString::null, 0,
+ this, 0);
+ connect(a_pview, SIGNAL(activated()), this, SLOT(viewPictures()));
+ a_vview = new QAction(tr("%1...", "app name").arg("" /*video_viewer.name() */ ),
+ Resource::loadIconSet(NULL /*video_viewer.icon() */ ), QString::null, 0,
+ this, 0);
+ connect(a_vview, SIGNAL(activated()), this, SLOT(viewVideos()));
+
+ a_settings =
+ new QAction(tr("Settings..."), Opie::Core::OResource::loadPixmap("camera2/settings", Opie::Core::OResource::SmallIcon),
+ QString::null, 0, this, 0);
+ connect(a_settings, SIGNAL(activated()), this, SLOT(doSettings()));
+
+ a_th_edit = new QAction(tr("Edit"), Opie::Core::OResource::loadPixmap("edit", Opie::Core::OResource::SmallIcon),
+ QString::null, 0, this, 0);
+ connect(a_th_edit, SIGNAL(activated()), this, SLOT(editThumb()));
+ a_th_del = new QAction(tr("Delete"), Opie::Core::OResource::loadPixmap("trash", Opie::Core::OResource::SmallIcon),
+ QString::null, 0, this, 0);
+ connect(a_th_del, SIGNAL(activated()), this, SLOT(delThumb()));
+ a_th_add =
+ new QAction(tr("Move to Contact..."), Opie::Core::OResource::loadPixmap("addressbook/generic-contact", Opie::Core::OResource::SmallIcon),
+ QString::null, 0, this, 0);
+ connect(a_th_add, SIGNAL(activated()), this, SLOT(moveToContact()));
+ a_send =
+ new QAction(tr("Beam to Contact..."), Opie::Core::OResource::loadPixmap("beam", Opie::Core::OResource::SmallIcon),
+ QString::null, 0, this, 0);
+ connect(a_send, SIGNAL(activated()), this, SLOT(sendFile()));
+
+
+#ifndef QTOPIA_PHONE
+ // Create Toolbars
+ QPEToolBar *bar = new QPEToolBar(this);
+ bar->setHorizontalStretchable(TRUE);
+ setToolBarsMovable(FALSE);
+
+ a_pview->addTo(bar);
+ if (video_supported)
+ a_vview->addTo(bar);
+ a_th_edit->addTo(bar);
+ a_th_del->addTo(bar);
+ a_th_add->addTo(bar);
+ a_send->addTo(bar);
+ a_settings->addTo(bar);
+#else
+ ContextMenu *contextMenu = new ContextMenu(this);
+ a_pview->addTo(contextMenu);
+ if (video_supported)
+ a_vview->addTo(contextMenu);
+ a_th_edit->addTo(contextMenu);
+ a_th_del->addTo(contextMenu);
+ a_th_add->addTo(contextMenu);
+ a_send->addTo(contextMenu);
+ a_settings->addTo(contextMenu);
+#endif
+
+ installEventFilter(camera->photo);
+ installEventFilter(camera->video);
+ camera->photo->installEventFilter(this);
+ camera->video->installEventFilter(this);
+
+ // Load the allowable sizes from the camera hardware.
+ photo_size = camera->videocaptureview->photoSizes();
+ video_size = camera->videocaptureview->videoSizes();
+
+ settings = new CameraSettings(this, 0, TRUE);
+ // load settings from config
+ Config cfg("Camera");
+ cfg.setGroup("General");
+ QString l = cfg.readEntry("location");
+
+#warning fixme
+ /*if ( !l.isEmpty() )
+ settings->location->setLocation(l);
+ */
+
+ storagepath = settings->location->documentPath();
+ cfg.setGroup("Photo");
+ int w;
+ w = cfg.readNumEntry("width", camera->videocaptureview->recommendedPhotoSize().width());
+ for (psize = 0; psize < (int) photo_size.count() - 1 && photo_size[psize].width() > w;)
+ psize++;
+ pquality = cfg.readNumEntry("quality", settings->photo_quality->value());
+ cfg.setGroup("Video");
+ w = cfg.readNumEntry("width", camera->videocaptureview->recommendedVideoSize().width());
+ for (vsize = 0; vsize < (int) video_size.count() - 1 && video_size[vsize].width() > w;)
+ vsize++;
+ vquality = cfg.readNumEntry("quality", settings->video_quality->value());
+ vframerate = cfg.readNumEntry("framerate", settings->video_framerate->value());
+
+ for (int i = 0; i < (int) photo_size.count(); i++) {
+ settings->photo_size->insertItem(tr("%1 x %2").arg(photo_size[i].width()).
+ arg(photo_size[i].height()));
+ }
+ for (int i = 0; i < (int) video_size.count(); i++) {
+ settings->video_size->insertItem(tr("%1 x %2").arg(video_size[i].width()).
+ arg(video_size[i].height()));
+ }
+
+ namehint = 0;
+ recording = FALSE;
+
+ preview();
+
+ if (!video_supported) {
+ // Room for longer text
+ camera->photo->setText(tr("Take Photo"));
+ camera->video->setEnabled(FALSE);
+ camera->video->hide();
+ }
+}
+
+CameraMainWindow::~CameraMainWindow()
+{
+}
+
+void CameraMainWindow::resizeEvent(QResizeEvent *)
+{
+ thumbw = width() / 5 - 4;
+ thumbh = thumbw * 3 / 4;
+ thumb[0]->setFixedHeight(thumbh + thmarg * 2);
+ loadThumbs();
+}
+
+bool CameraMainWindow::event(QEvent * e)
+{
+ if (e->type() == QEvent::WindowActivate) {
+ if (cur_thumb < 0)
+ camera->videocaptureview->setLive();
+ }
+ else if (e->type() == QEvent::WindowDeactivate) {
+ camera->videocaptureview->setLive(-1);
+ }
+ return QMainWindow::event(e);
+}
+
+bool CameraMainWindow::eventFilter(QObject * o, QEvent * e)
+{
+ if (e->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = (QKeyEvent *) e;
+
+#if QTOPIA_PHONE
+ if (!ke->isAutoRepeat()) {
+ if (ke->key() == Key_1) {
+ takePhoto();
+ return TRUE;
+ }
+ else if (ke->key() == Key_2) {
+ toggleVideo();
+ return TRUE;
+ }
+ }
+#endif
+ if (ke->key() == Key_Up) {
+ camera->photo->setFocus();
+ return TRUE;
+ }
+ else if (ke->key() == Key_Down) {
+ thumb[0]->setFocus();
+ return TRUE;
+ }
+ else if (ke->key() == Key_Left) {
+ if (o == camera->video) {
+ camera->photo->setFocus();
+ return TRUE;
+ }
+ else {
+ if (o == thumb[0])
+ return TRUE;
+ for (int i = 1; i < nthumb; ++i) {
+ if (o == thumb[i]) {
+ thumb[i - 1]->setFocus();
+ return TRUE;
+ }
+ }
+ }
+ }
+ else if (ke->key() == Key_Right) {
+ if (o == camera->photo) {
+ camera->video->setFocus();
+ return TRUE;
+ }
+ else {
+ if (o == thumb[nthumb - 1])
+ return TRUE;
+ for (int i = 0; i < nthumb - 1; ++i) {
+ if (o == thumb[i]) {
+ thumb[i + 1]->setFocus();
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ else if (e->type() == QEvent::FocusIn) {
+ if (o == camera->photo)
+ camera->photo->setText(tr("Take Photo"));
+ updateActions();
+ }
+ else if (e->type() == QEvent::FocusOut) {
+ if (o == camera->photo)
+ camera->photo->setText(tr("Activate Camera"));
+ }
+ return QWidget::eventFilter(o, e);
+}
+
+void CameraMainWindow::updateActions()
+{
+ bool p = FALSE, v = FALSE;
+ QWidget *foc = focusWidget();
+ if (foc == camera->photo) {
+ p = TRUE;
+ v = FALSE;
+ }
+ else if (foc == camera->video) {
+ v = TRUE;
+ p = FALSE;
+ }
+ a_pview->setEnabled(p);
+ a_vview->setEnabled(v);
+ a_settings->setEnabled(p || v);
+ bool th = !p && !v;
+ if (th) {
+ int i;
+ for (i = 0; i < nthumb; i++) {
+ if (thumb[i] == foc) {
+ selectThumb(i);
+ break;
+ }
+ }
+ if (i == nthumb || !thumb[i]->pixmap())
+ th = FALSE;
+ }
+ else {
+ selectThumb(-1);
+ }
+}
+
+void CameraMainWindow::viewPictures()
+{
+#warning fixme
+// ServiceRequest req("PhotoEdit","showCategory(int)");
+// req << camcat;
+// req.send();
+}
+
+void CameraMainWindow::viewVideos()
+{
+#warning fixme
+// Service::appLnk("Open/video/mpeg").execute();
+}
+
+void CameraMainWindow::doSettings()
+{
+ bool v = video_supported;
+#ifdef QTOPIA_PHONE
+ bool p;
+ p = a_pview->isEnabled();
+ v = v && a_vview->isEnabled();
+ if (p)
+ settings->photo->show();
+ else
+ settings->photo->hide();
+#endif
+ if (v)
+ settings->video->show();
+ else
+ settings->video->hide();
+ settings->photo_size->setCurrentItem(psize);
+ settings->video_size->setCurrentItem(vsize);
+ settings->photo_quality->setValue(pquality);
+ settings->video_quality->setValue(vquality);
+ settings->video_framerate->setValue(vframerate);
+ settings->video_quality_n->setFixedWidth(fontMetrics().width("100"));
+ settings->photo_quality_n->setFixedWidth(fontMetrics().width("100"));
+
+ if (QPEApplication::execDialog(settings)) {
+ confirmSettings();
+ }
+ else {
+#warning fixme
+// settings->location->setLocation(storagepath);
+ }
+}
+
+void CameraMainWindow::confirmSettings()
+{
+ storagepath = settings->location->documentPath();
+ psize = settings->photo_size->currentItem();
+ vsize = settings->video_size->currentItem();
+ pquality = settings->photo_quality->value();
+ vquality = settings->video_quality->value();
+ vframerate = settings->video_framerate->value();
+
+ // save settings
+ Config cfg("Camera");
+ cfg.setGroup("General");
+ cfg.writeEntry("location", storagepath);
+ cfg.setGroup("Photo");
+ cfg.writeEntry("width", photo_size[psize].width());
+ cfg.writeEntry("quality", pquality);
+ cfg.setGroup("Video");
+ cfg.writeEntry("width", video_size[vsize].width());
+ cfg.writeEntry("quality", vquality);
+ cfg.writeEntry("framerate", vframerate);
+
+ loadThumbs();
+
+ preview();
+}
+
+static int cmpDocLnk(const void *a, const void *b)
+{
+ const DocLnk *la = *(const DocLnk **) a;
+ const DocLnk *lb = *(const DocLnk **) b;
+ QFileInfo fa(la->linkFileKnown()? la->linkFile() : la->file());
+ QFileInfo fb(lb->linkFileKnown()? lb->linkFile() : lb->file());
+ return fa.lastModified().secsTo(fb.lastModified());
+}
+
+void CameraMainWindow::loadThumbs()
+{
+ if (storagepath.isEmpty()) {
+ updateActions();
+ return;
+ }
+
+ DocLnkSet set(storagepath, "image/jpeg");
+ const QList < DocLnk > &l = set.children();
+
+ DocLnk *lnk;
+ DocLnk **array = new DocLnk *[l.count()];
+ int n = 0;
+ for (QListIterator < DocLnk > it(l); (lnk = it.current()); ++it) {
+ if (lnk->categories().contains(camcat))
+ array[n++] = lnk;
+ }
+ qsort(array, n, sizeof(array[0]), cmpDocLnk);
+ for (int i = 0; i < nthumb; i++) {
+ QPixmap pm;
+ if (i < n) {
+ picturefile[i] = *array[i];
+ QImage img = Image::loadScaled(picturefile[i].file(), thumbw, thumbh);
+ pm.convertFromImage(img);
+ }
+ if (pm.isNull()) {
+ thumb[i]->setText("");
+ }
+ else {
+ thumb[i]->setPixmap(pm);
+ }
+ thumb[i]->setEnabled(!pm.isNull());
+ }
+ if (cur_thumb >= 0)
+ selectThumb(cur_thumb);
+
+ if (!camera->videocaptureview->available()) {
+ camera->photo->setEnabled(FALSE);
+ camera->video->setEnabled(FALSE);
+ if (!n) {
+ thumb[0]->setEnabled(FALSE);
+ }
+ else {
+ thumb[0]->setFocus();
+ thumb[0]->setEnabled(TRUE);
+ }
+ }
+
+ updateActions();
+}
+
+void CameraMainWindow::delThumb(int th)
+{
+ switch (QMessageBox::warning(0, tr("Confirmation"),
+ tr("<qt>Delete '%1'?</qt>",
+ "%1 = file name").arg(picturefile[th].name()), QMessageBox::Yes,
+ QMessageBox::No)) {
+ case QMessageBox::Yes:
+ picturefile[th].removeFiles();
+
+ // Rhys Hack - if we have just deleted the last image and there
+ // is no camera connected, then exit the application. This
+ // avoids a focus problem where it is impossible to exit with
+ // the back button due to the focus being in a stupid place.
+ loadThumbs();
+ if (!camera->videocaptureview->available() && !(thumb[0]->isEnabled())) {
+ close();
+ }
+ break;
+ default:
+ //nothing
+ break;
+ }
+}
+
+void CameraMainWindow::pushThumb(const DocLnk & f, const QImage & img)
+{
+ for (int i = nthumb; --i;) {
+ bool en = thumb[i - 1]->isEnabled();
+ thumb[i]->setEnabled(en);
+ picturefile[i] = picturefile[i - 1];
+ const QPixmap *pm = thumb[i - 1]->pixmap();
+ if (en && pm) {
+ thumb[i]->setPixmap(*pm);
+ }
+ else {
+ thumb[i]->setText("");
+ }
+ }
+ QPixmap pm;
+ QSize sz = Image::aspectScaleSize(img.width(), img.height(), thumbw, thumbh);
+ QImage simg = img.smoothScale(sz.width(), sz.height());
+ pm.convertFromImage(simg);
+ thumb[0]->setPixmap(pm);
+ thumb[0]->setEnabled(TRUE);
+ picturefile[0] = f;
+}
+
+void CameraMainWindow::takePhoto()
+{
+ if (camera->photo != focusWidget()) {
+ camera->photo->setFocus();
+ return;
+ }
+ QSize size = photo_size[psize];
+ if (size == camera->videocaptureview->captureSize() ||
+ camera->videocaptureview->refocusDelay() == 0) {
+
+ // We can grab the current image immediately.
+ takePhotoNow();
+
+ }
+ else {
+
+ // Change the camera size and then wait for the camera to refocus.
+ camera->videocaptureview->setCaptureSize(size);
+ refocusTimer->start(camera->videocaptureview->refocusDelay(), TRUE);
+
+ }
+}
+
+void CameraMainWindow::takePhotoNow()
+{
+ QImage img = camera->videocaptureview->image();
+
+ if (inSnapMode()) {
+ QCopEnvelope e(snap_ch, "valueSupplied(QString,QImage)");
+ QSize s = Image::aspectScaleSize(img.width(), img.height(), snap_maxw, snap_maxh);
+ e << snap_id << img.smoothScale(s.width(), s.height());
+ setSnapMode(FALSE);
+ close();
+ }
+ else {
+ DocLnk f;
+ //f.setLocation(storagepath);
+ f.setType("image/jpeg");
+ QDateTime dt = QDateTime::currentDateTime();
+ QString date = dt.toString();
+ f.setName(tr("Photo, " + date));
+
+ QArray < int >c(1);
+ c[0] = camcat;
+ f.setCategories(c);
+ img.save(f.file(), "JPEG", pquality); // Save the image in its original size.
+ f.writeLink();
+ pushThumb(f, img);
+ }
+
+ preview();
+}
+
+bool CameraMainWindow::inSnapMode() const
+{
+ return !snap_ch.isEmpty();
+}
+
+void CameraMainWindow::setSnapMode(bool y)
+{
+ if (y) {
+ camera->thumbs->hide();
+ camera->video->hide();
+ }
+ else {
+ camera->thumbs->show();
+ if (video_supported)
+ camera->video->show();
+ else
+ camera->video->hide();
+ snap_ch = QString::null;
+ }
+}
+
+void CameraMainWindow::toggleVideo()
+{
+ if (recording)
+ stopVideo();
+ else
+ startVideo();
+ recording = !recording;
+ camera->video->setText(recording ? tr("Stop") : tr("Video"));
+ camera->photo->setEnabled(!recording);
+ for (int i = 0; i < nthumb; i++)
+ thumb[i]->setEnabled(!recording && thumb[i]->pixmap());
+}
+
+void CameraMainWindow::startVideo()
+{
+ // XXX eg. MJPG
+}
+void CameraMainWindow::stopVideo()
+{
+}
+
+void CameraMainWindow::thumbClicked(int i)
+{
+ selectThumb(i);
+}
+
+void CameraMainWindow::editThumb()
+{
+ picturefile[cur_thumb].execute();
+}
+
+void CameraMainWindow::selectThumb(int i)
+{
+ cur_thumb = i;
+ if (i >= 0) {
+ QImage img(picturefile[i].file());
+ camera->videocaptureview->setStill(img);
+ thumb[i]->setFocus();
+ }
+ else {
+ camera->videocaptureview->setLive();
+ }
+ a_th_edit->setEnabled(i >= 0);
+ a_th_del->setEnabled(i >= 0);
+ a_th_add->setEnabled(i >= 0);
+ a_send->setEnabled(i >= 0);
+}
+
+void CameraMainWindow::moveToContact()
+{
+ if (cur_thumb >= 0) {
+#warning fixme
+// QCopEnvelope e(Service::channel("Contacts"),"setContactImage(QImage)");
+// QImage img;
+// img.load(picturefile[cur_thumb].file());
+// e << img;
+ }
+}
+
+void CameraMainWindow::delThumb()
+{
+ if (cur_thumb >= 0) {
+ int d = cur_thumb;
+ if (cur_thumb > 0)
+ selectThumb(cur_thumb - 1);
+ delThumb(d);
+ }
+}
+
+void CameraMainWindow::linkChanged(const QString &)
+{
+ loadThumbs();
+}
+
+void CameraMainWindow::appMessage(const QCString & msg, const QByteArray & data)
+{
+ if (msg == "getImage(QCString,QString,int,int,QImage)") {
+ QDataStream ds(data, IO_ReadOnly);
+ ds >> snap_ch >> snap_id >> snap_maxw >> snap_maxh;
+ setSnapMode(TRUE);
+ QPEApplication::setKeepRunning();
+ }
+}
+
+void CameraMainWindow::preview()
+{
+ if (camera->videocaptureview->refocusDelay() > 200) {
+ camera->videocaptureview->setCaptureSize(photo_size[psize]);
+ }
+ else {
+ camera->videocaptureview->setCaptureSize(camera->videocaptureview->
+ recommendedPreviewSize());
+ }
+}
+
+void CameraMainWindow::sendFile()
+{
+ if (cur_thumb >= 0) {
+ //copy file
+ QFile input(picturefile[cur_thumb].file());
+ if (!input.open(IO_ReadOnly)) {
+ return; //error
+ }
+ QFile output(picfile);
+ if (!output.open(IO_WriteOnly)) {
+ return;
+ }
+
+ const int BUFFER_SIZE = 1024;
+ Q_INT8 buffer[BUFFER_SIZE];
+
+ QDataStream srcStr(&input);
+ QDataStream destStr(&output);
+
+ while (!srcStr.atEnd()) {
+ int i = 0;
+ while (!srcStr.atEnd() && i < BUFFER_SIZE) {
+ srcStr >> buffer[i];
+ i++;
+ }
+ for (int k = 0; k < i; k++) {
+ destStr << buffer[k];
+ }
+ }
+
+#warning fixme
+// QCopEnvelope e(Service::channel("Email"),"writeMessage(QString,QString,QStringList,QStringList)");
+// e << QString() << QString() << QStringList() << QStringList( QString( picfile ) );
+ }
+}
+
+void ThumbButton::drawButtonLabel(QPainter * p)
+{
+ const QPixmap *pm = pixmap();
+ if (pm) {
+ QSize s = (size() - pm->size()) / 2;
+ p->drawPixmap(s.width(), s.height(), *pm);
+ }
+}
+
+ThumbButton::ThumbButton(QWidget * parent, const char *name):QToolButton(parent, name)
+{
+}
+
diff --git a/noncore/multimedia/camera2/mainwindow.h b/noncore/multimedia/camera2/mainwindow.h
new file mode 100644
index 0000000..d6c5a7e
--- a/dev/null
+++ b/noncore/multimedia/camera2/mainwindow.h
@@ -0,0 +1,132 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "camerabase.h"
+#include <qvaluelist.h>
+#include <qmainwindow.h>
+#include <qpe/applnk.h>
+
+class LocationCombo;
+class QAction;
+class QTimer;
+class CameraSettings;
+
+
+class CameraMainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ static QString appName() { return QString::fromLatin1("camera2"); }
+
+ CameraMainWindow( QWidget *parent=0, const char *name=0, WFlags fl=0 );
+ ~CameraMainWindow();
+
+public slots:
+ void takePhoto();
+ void toggleVideo();
+ void selectThumb(int i);
+ void thumbClicked(int i);
+
+private slots:
+ void viewPictures();
+ void viewVideos();
+ void doSettings();
+ void appMessage(const QCString& msg, const QByteArray& data);
+ void editThumb();
+ void delThumb();
+ void moveToContact();
+ void takePhotoNow();
+ void sendFile();
+ void linkChanged(const QString&);
+
+private:
+ bool event(QEvent* e);
+ void updateActions();
+ void resizeEvent(QResizeEvent*);
+
+ bool eventFilter(QObject*, QEvent*);
+ QString nextFileName();
+ void loadThumbs();
+ void pushThumb(const DocLnk& f, const QImage& img);
+ static const int nthumb = 5;
+ QToolButton* thumb[nthumb];
+ DocLnk picturefile[nthumb];
+ int cur_thumb;
+ void delThumb(int th);
+
+ // Settings
+ void confirmSettings();
+ CameraSettings *settings;
+ QString storagepath;
+ int thumbw;
+ int thumbh;
+ int psize;
+ int vsize;
+ int pquality;
+ int vquality;
+ int vframerate;
+
+ // Snap
+ QCString snap_ch;
+ QString snap_id;
+ int snap_maxw, snap_maxh;
+ bool inSnapMode() const;
+ void setSnapMode(bool);
+
+ CameraBase *camera;
+
+ int namehint;
+ QAction *a_pview, *a_vview, *a_settings;
+ QAction *a_th_edit, *a_th_del, *a_th_add;
+ QAction *a_send;
+ QValueList<QSize> photo_size;
+ QValueList<QSize> video_size;
+
+ QTimer *refocusTimer;
+ QString picfile;
+
+ bool recording;
+ void stopVideo();
+ void startVideo();
+
+ void preview();
+
+ int camcat;
+};
+
+#endif
+
diff --git a/noncore/multimedia/camera2/opie-camera2.control b/noncore/multimedia/camera2/opie-camera2.control
new file mode 100644
index 0000000..a2d0700
--- a/dev/null
+++ b/noncore/multimedia/camera2/opie-camera2.control
@@ -0,0 +1,10 @@
+Package: opie-camera2
+Files: bin/camerapics/camera2 apps/Applications/camera2.desktop
+Priority: optional
+Section: opie/multimedia
+Maintainer: Lorn "ljp" Potter <lorn.potter@trolltech.com>
+Architecture: arm
+Version: 1.0.1$EXTRAVERSION
+Depends: libqpe1, libopiecore2, libopieui2
+Description: A Camera Application
+ A Camera Application to use with Video4Linux.
diff --git a/noncore/multimedia/camera2/thumbbutton.h b/noncore/multimedia/camera2/thumbbutton.h
new file mode 100644
index 0000000..f7ca3b4
--- a/dev/null
+++ b/noncore/multimedia/camera2/thumbbutton.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef THUMBBUTTON_H
+#define THUMBBUTTON_H
+
+#include <qtoolbutton.h>
+
+class ThumbButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ ThumbButton( QWidget *parent, const char* name );
+
+ void drawButtonLabel( QPainter * );
+};
+
+#endif
+
diff --git a/noncore/multimedia/camera2/videocaptureview.cpp b/noncore/multimedia/camera2/videocaptureview.cpp
new file mode 100644
index 0000000..410634a
--- a/dev/null
+++ b/noncore/multimedia/camera2/videocaptureview.cpp
@@ -0,0 +1,599 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include "videocaptureview.h"
+#include <qimage.h>
+#include <qpainter.h>
+#ifdef Q_WS_QWS
+#include <qgfx_qws.h>
+#include <qdirectpainter_qws.h>
+#endif
+
+#ifdef __linux__
+#define HAVE_VIDEO4LINUX 1
+#endif
+
+#ifdef HAVE_VIDEO4LINUX
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <linux/videodev.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#endif /* HAVE_VIDEO4LINUX */
+
+class VideoCapture {
+ public:
+ VideoCapture();
+ ~VideoCapture();
+
+ bool hasCamera() const;
+ void getCameraImage(QImage & img, bool copy = FALSE);
+
+ QValueList < QSize > photoSizes() const;
+ QValueList < QSize > videoSizes() const;
+
+ QSize recommendedPhotoSize() const;
+ QSize recommendedVideoSize() const;
+ QSize recommendedPreviewSize() const;
+
+ QSize captureSize() const;
+ void setCaptureSize(QSize size);
+
+ uint refocusDelay() const;
+ int minimumFramePeriod() const;
+
+ private:
+#ifdef HAVE_VIDEO4LINUX
+ int fd;
+ int width, height;
+ struct video_capability caps;
+ struct video_mbuf mbuf;
+ unsigned char *frames;
+ int currentFrame;
+
+ void setupCamera(QSize size);
+ void shutdown();
+#endif
+};
+
+#ifdef HAVE_VIDEO4LINUX
+
+#define VIDEO_DEVICE "/dev/video"
+
+bool VideoCapture::hasCamera() const
+{
+ return (fd != -1);
+}
+
+QSize VideoCapture::captureSize() const
+{
+ return QSize(width, height);
+}
+
+uint VideoCapture::refocusDelay() const
+{
+ return 250;
+}
+
+int VideoCapture::minimumFramePeriod() const
+{
+ return 40; // milliseconds
+}
+
+VideoCapture::VideoCapture()
+{
+ setupCamera(QSize(0, 0));
+}
+
+VideoCapture::~VideoCapture()
+{
+ shutdown();
+}
+
+void VideoCapture::setupCamera(QSize size)
+{
+ qWarning(" VideoCapture::setupCamera");
+ // Clear important variables.
+ frames = 0;
+ currentFrame = 0;
+ width = 640;
+ height = 480;
+ caps.minwidth = width;
+ caps.minheight = height;
+ caps.maxwidth = width;
+ caps.maxheight = height;
+
+ // Open the video device.
+ fd = open(VIDEO_DEVICE, O_RDWR);
+ if (fd == -1) {
+ qWarning("%s: %s", VIDEO_DEVICE, strerror(errno));
+ return;
+ }
+
+ // Get the device's current capabilities.
+ memset(&caps, 0, sizeof(caps));
+ if (ioctl(fd, VIDIOCGCAP, &caps) < 0) {
+ qWarning("%s: could not retrieve the video capabilities", VIDEO_DEVICE);
+ close(fd);
+ fd = -1;
+ return;
+ }
+
+ // Change the channel to the first-connected camera, skipping TV inputs.
+ // If there are multiple cameras, this may need to be modified.
+ int chan;
+ struct video_channel chanInfo;
+ qWarning("available video capture inputs:");
+ for (chan = 0; chan < caps.channels; ++chan) {
+ chanInfo.channel = chan;
+ if (ioctl(fd, VIDIOCGCHAN, &chanInfo) >= 0) {
+ if (chanInfo.type == VIDEO_TYPE_CAMERA)
+ qWarning(" %s (camera)", chanInfo.name);
+ else if (chanInfo.type == VIDEO_TYPE_TV)
+ qWarning(" %s (tv)", chanInfo.name);
+ else
+ qWarning(" %s (unknown)", chanInfo.name);
+ }
+ }
+ for (chan = 0; chan < caps.channels; ++chan) {
+ chanInfo.channel = chan;
+ if (ioctl(fd, VIDIOCGCHAN, &chanInfo) >= 0) {
+ if (chanInfo.type == VIDEO_TYPE_CAMERA) {
+ qWarning("selecting camera on input %s", chanInfo.name);
+ if (ioctl(fd, VIDIOCSCHAN, &chan) < 0) {
+ qWarning("%s: could not set the channel", VIDEO_DEVICE);
+ }
+ break;
+ }
+ }
+ }
+
+ // Set the desired picture mode to RGB32.
+ struct video_picture pict;
+ memset(&pict, 0, sizeof(pict));
+ ioctl(fd, VIDIOCGPICT, &pict);
+ pict.palette = VIDEO_PALETTE_RGB32;
+ if (ioctl(fd, VIDIOCSPICT, &pict) < 0) {
+ qWarning("%s: could not set the picture mode", VIDEO_DEVICE);
+ close(fd);
+ fd = -1;
+ return;
+ }
+
+ // Determine the capture size to use. Zero indicates "preview mode".
+ if (size.width() == 0) {
+ size = QSize(caps.minwidth, caps.minheight);
+ }
+
+ // Get the current capture window.
+ struct video_window wind;
+ memset(&wind, 0, sizeof(wind));
+ ioctl(fd, VIDIOCGWIN, &wind);
+
+ // Adjust the capture size to match the camera's aspect ratio.
+ if (caps.maxwidth > 0 && caps.maxheight > 0) {
+ if (size.width() > size.height()) {
+ size = QSize(size.height() * caps.maxwidth / caps.maxheight, size.height());
+ }
+ else {
+ size = QSize(size.width(), size.width() * caps.maxheight / caps.maxwidth);
+ }
+ }
+
+ // Set the new capture window.
+ wind.x = 0;
+ wind.y = 0;
+ wind.width = size.width();
+ wind.height = size.height();
+ if (ioctl(fd, VIDIOCSWIN, &wind) < 0) {
+ qWarning("%s: could not set the capture window", VIDEO_DEVICE);
+ }
+
+ // Re-read the capture window, to see what it was adjusted to.
+ ioctl(fd, VIDIOCGWIN, &wind);
+ width = wind.width;
+ height = wind.height;
+
+ // Enable mmap-based access to the camera.
+ memset(&mbuf, 0, sizeof(mbuf));
+ if (ioctl(fd, VIDIOCGMBUF, &mbuf) < 0) {
+ qWarning("%s: mmap-based camera access is not available", VIDEO_DEVICE);
+ close(fd);
+ fd = -1;
+ return;
+ }
+
+ // Mmap the designated memory region.
+ frames = (unsigned char *) mmap(0, mbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (!frames || frames == (unsigned char *) (long) (-1)) {
+ qWarning("%s: could not mmap the device", VIDEO_DEVICE);
+ close(fd);
+ fd = -1;
+ return;
+ }
+
+ // Start capturing of the first frame.
+ struct video_mmap capture;
+ currentFrame = 0;
+ capture.frame = currentFrame;
+ capture.width = width;
+ capture.height = height;
+ capture.format = VIDEO_PALETTE_RGB32;
+ ioctl(fd, VIDIOCMCAPTURE, &capture);
+}
+
+void VideoCapture::shutdown()
+{
+ if (frames != 0) {
+ munmap(frames, mbuf.size);
+ frames = 0;
+ }
+ if (fd != -1) {
+ int flag = 0;
+ ioctl(fd, VIDIOCSYNC, 0);
+ ioctl(fd, VIDIOCCAPTURE, &flag);
+ close(fd);
+ fd = -1;
+ }
+}
+
+void VideoCapture::getCameraImage(QImage & img, bool copy)
+{
+ if (fd == -1) {
+ if (img.isNull()) {
+ img.create(width, height, 32);
+ }
+ return;
+ }
+
+ // Start capturing the next frame (we alternate between 0 and 1).
+ int frame = currentFrame;
+ struct video_mmap capture;
+ if (mbuf.frames > 1) {
+ currentFrame = !currentFrame;
+ capture.frame = currentFrame;
+ capture.width = width;
+ capture.height = height;
+ capture.format = VIDEO_PALETTE_RGB32;
+ ioctl(fd, VIDIOCMCAPTURE, &capture);
+ }
+
+ // Wait for the current frame to complete.
+ ioctl(fd, VIDIOCSYNC, &frame);
+
+ // Create an image that refers directly to the kernel's
+ // frame buffer, to avoid having to copy the data.
+ if (!copy) {
+ img = QImage(frames + mbuf.offsets[frame], width, height, 32, 0, 0, QImage::IgnoreEndian);
+ }
+ else {
+ img.create(width, height, 32);
+ memcpy(img.bits(), frames + mbuf.offsets[frame], width * height * 4);
+ }
+
+ // Queue up another frame if the device only supports one at a time.
+ if (mbuf.frames <= 1) {
+ capture.frame = currentFrame;
+ capture.width = width;
+ capture.height = height;
+ capture.format = VIDEO_PALETTE_RGB32;
+ ioctl(fd, VIDIOCMCAPTURE, &capture);
+ }
+}
+
+QValueList < QSize > VideoCapture::photoSizes() const
+{
+ QValueList < QSize > list;
+ list.append(QSize(caps.maxwidth, caps.maxheight));
+ if (caps.maxwidth != caps.minwidth || caps.maxheight != caps.minheight)
+ list.append(QSize(caps.minwidth, caps.minheight));
+ return list;
+}
+
+QValueList < QSize > VideoCapture::videoSizes() const
+{
+ // We use the same sizes for both.
+ return photoSizes();
+}
+
+QSize VideoCapture::recommendedPhotoSize() const
+{
+ return QSize(caps.maxwidth, caps.maxheight);
+}
+
+QSize VideoCapture::recommendedVideoSize() const
+{
+ return QSize(caps.minwidth, caps.minheight);
+}
+
+QSize VideoCapture::recommendedPreviewSize() const
+{
+ return QSize(caps.minwidth, caps.minheight);
+}
+
+void VideoCapture::setCaptureSize(QSize size)
+{
+ if (size.width() != width || size.height() != height) {
+ shutdown();
+ setupCamera(size);
+ }
+}
+
+#else /* !HAVE_VIDEO4LINUX */
+
+// Dummy implementation for systems without video.
+
+VideoCapture::VideoCapture()
+{
+}
+
+VideoCapture::~VideoCapture()
+{
+}
+
+bool VideoCapture::hasCamera() const
+{
+ return TRUE;
+}
+
+QSize VideoCapture::captureSize() const
+{
+ return QSize(640, 480);
+}
+
+uint VideoCapture::refocusDelay() const
+{
+ return 0;
+}
+
+int VideoCapture::minimumFramePeriod() const
+{
+ return 100;
+}
+
+static unsigned int nextrand()
+{
+#define A 16807
+#define M 2147483647
+#define Q 127773
+#define R 2836
+ static unsigned int rnd = 1;
+ unsigned long hi = rnd / Q;
+ unsigned long lo = rnd % Q;
+ unsigned long test = A * lo - R * hi;
+ if (test > 0)
+ rnd = test;
+ else
+ rnd = test + M;
+ return rnd;
+}
+
+void VideoCapture::getCameraImage(QImage & img, bool)
+{
+ // Just generate something dynamic (rectangles)
+ static QImage cimg;
+ int x, y, w, h;
+ if (cimg.isNull()) {
+ x = y = 0;
+ w = 640;
+ h = 480;
+ cimg.create(w, h, 32);
+ }
+ else {
+ w = nextrand() % (cimg.width() - 10) + 10;
+ h = nextrand() % (cimg.height() - 10) + 10;
+ x = nextrand() % (cimg.width() - w);
+ y = nextrand() % (cimg.height() - h);
+ }
+ QRgb c = qRgb(nextrand() % 255, nextrand() % 255, nextrand() % 255);
+ for (int j = 0; j < h; j++) {
+ QRgb *l = (QRgb *) cimg.scanLine(y + j) + x;
+ for (int i = 0; i < w; i++)
+ l[i] = c;
+ }
+ img = cimg;
+}
+
+QValueList < QSize > VideoCapture::photoSizes() constconst
+{
+ QValueList < QSize > list;
+ list.append(QSize(640, 480));
+ list.append(QSize(320, 240));
+ return list;
+}
+
+QValueList < QSize > VideoCapture::videoSizes() constconst
+{
+ QValueList < QSize > list;
+ list.append(QSize(640, 480));
+ list.append(QSize(320, 240));
+ return list;
+}
+
+QSize VideoCapture::recommendedPhotoSize() const
+{
+ return QSize(640, 480);
+}
+
+QSize VideoCapture::recommendedVideoSize() const
+{
+ return QSize(320, 240);
+}
+
+QSize VideoCapture::recommendedPreviewSize() const
+{
+ return QSize(320, 240);
+}
+
+void VideoCapture::setCaptureSize(QSize size)
+{
+}
+
+#endif /* !HAVE_VIDEO4LINUX */
+
+VideoCaptureView::VideoCaptureView(QWidget * parent, const char *name, WFlags fl):QWidget(parent,
+ name, fl)
+{
+ capture = new VideoCapture();
+ QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ setSizePolicy(sp);
+ tid_update = 0;
+ setLive();
+}
+
+VideoCaptureView::~VideoCaptureView()
+{
+ delete capture;
+}
+
+void VideoCaptureView::setLive(int period)
+{
+ if (tid_update)
+ killTimer(tid_update);
+ if (period == 0)
+ tid_update = startTimer(capture->minimumFramePeriod());
+ else if (period > 0)
+ tid_update = startTimer(period);
+ else
+ tid_update = 0;
+}
+
+void VideoCaptureView::setStill(const QImage & i)
+{
+ setLive(-1);
+ img = i;
+ repaint(TRUE);
+}
+
+QValueList < QSize > VideoCaptureView::photoSizes() const
+{
+ return capture->photoSizes();
+}
+
+QValueList < QSize > VideoCaptureView::videoSizes() const
+{
+ return capture->videoSizes();
+}
+
+QSize VideoCaptureView::recommendedPhotoSize() const
+{
+ return capture->recommendedPhotoSize();
+}
+
+QSize VideoCaptureView::recommendedVideoSize() const
+{
+ return capture->recommendedVideoSize();
+}
+
+QSize VideoCaptureView::recommendedPreviewSize() const
+{
+ return capture->recommendedPreviewSize();
+}
+
+QSize VideoCaptureView::captureSize() const
+{
+ return capture->captureSize();
+}
+
+void VideoCaptureView::setCaptureSize(QSize size)
+{
+ capture->setCaptureSize(size);
+}
+
+uint VideoCaptureView::refocusDelay() const
+{
+ return capture->refocusDelay();
+}
+
+bool VideoCaptureView::available() const
+{
+ return capture->hasCamera();
+}
+
+void VideoCaptureView::paintEvent(QPaintEvent *)
+{
+ if (tid_update && !capture->hasCamera()) {
+ QPainter p(this);
+ p.drawText(rect(), AlignCenter, tr("No Camera"));
+ return;
+ }
+
+ if (tid_update)
+ capture->getCameraImage(img);
+ int w = img.width();
+ int h = img.height();
+
+ if (!w || !h)
+ return;
+
+ if (width() * w > height() * h) {
+ w = w * height() / h;
+ h = height();
+ }
+ else {
+ h = h * width() / w;
+ w = width();
+ }
+
+ if (qt_screen->transformOrientation() == 0) {
+ // Stretch and draw the image.
+ QDirectPainter p(this);
+ QGfx *gfx = p.internalGfx();
+ if (gfx) {
+ gfx->setSource(&img);
+ gfx->setAlphaType(QGfx::IgnoreAlpha);
+ gfx->stretchBlt((width() - w) / 2, (height() - h) / 2, w, h, img.width(), img.height());
+ }
+ }
+ else {
+ // This code is nowhere near efficient enough (hence the above).
+ // TODO - handle rotations during direct painting.
+ QImage scimg = img.smoothScale(w, h);
+ QPainter p(this);
+ p.drawImage((width() - w) / 2, (height() - h) / 2, scimg);
+ }
+}
+
+void VideoCaptureView::timerEvent(QTimerEvent *)
+{
+ repaint(FALSE);
+}
+
diff --git a/noncore/multimedia/camera2/videocaptureview.h b/noncore/multimedia/camera2/videocaptureview.h
new file mode 100644
index 0000000..68c3b68
--- a/dev/null
+++ b/noncore/multimedia/camera2/videocaptureview.h
@@ -0,0 +1,82 @@
+/**********************************************************************
+** Copyright (C) 2000-2006 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This program is free software; you can redistribute it and/or modify it
+** under the terms of the GNU General Public License as published by the
+** Free Software Foundation; either version 2 of the License, or (at your
+** option) any later version.
+**
+** A copy of the GNU GPL license version 2 is included in this package as
+** LICENSE.GPL.
+**
+** This program is distributed in the hope that it will be useful, but
+** WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+** See the GNU General Public License for more details.
+**
+** In addition, as a special exception Trolltech gives permission to link
+** the code of this program with Qtopia applications copyrighted, developed
+** and distributed by Trolltech under the terms of the Qtopia Personal Use
+** License Agreement. You must comply with the GNU General Public License
+** in all respects for all of the code used other than the applications
+** licensed under the Qtopia Personal Use License Agreement. If you modify
+** this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef VIDEOVIEW_H
+#define VIDEOVIEW_H
+
+#include <qwidget.h>
+#include <qimage.h>
+#include <qvaluelist.h>
+
+class VideoCapture;
+
+
+class VideoCaptureView : public QWidget
+{
+ Q_OBJECT
+
+public:
+ VideoCaptureView( QWidget *parent=0, const char *name=0, WFlags fl=0 );
+ ~VideoCaptureView();
+
+ bool available() const;
+
+ QImage image() const { return img; }
+ void setLive(int period=0);
+ void setStill(const QImage&);
+
+ QValueList<QSize> photoSizes() const;
+ QValueList<QSize> videoSizes() const;
+
+ QSize recommendedPhotoSize() const;
+ QSize recommendedVideoSize() const;
+ QSize recommendedPreviewSize() const;
+
+ QSize captureSize() const;
+ void setCaptureSize( QSize size );
+
+ uint refocusDelay() const;
+
+protected:
+ void paintEvent(QPaintEvent*);
+ void timerEvent(QTimerEvent*);
+
+private:
+ QImage img;
+ int tid_update;
+ VideoCapture *capture;
+};
+
+#endif
+
diff --git a/packages b/packages
index 08e1ea9..d45dbf7 100644
--- a/packages
+++ b/packages
@@ -1,263 +1,264 @@
CONFIG_ABOUTAPPLET core/applets/aboutapplet aboutapplet.pro
CONFIG_ADDRESSBOOK core/pim/addressbook addressbook.pro
CONFIG_ADVANCEDFM noncore/apps/advancedfm advancedfm.pro
CONFIG_APPEARANCE2 noncore/settings/appearance2 appearance2.pro
CONFIG_APPSKEY noncore/settings/appskey appskey.pro
CONFIG_AQPKG noncore/settings/aqpkg aqpkg.pro
CONFIG_AUTOROTATEAPPLET noncore/applets/autorotateapplet autorotateapplet.pro
CONFIG_BACKGAMMON noncore/games/backgammon backgammon.pro
CONFIG_BACKUP noncore/settings/backup backup.pro
CONFIG_BARTENDER noncore/apps/opie-bartender bartender.pro
CONFIG_BATTERYAPPLET core/applets/batteryapplet batteryapplet.pro
CONFIG_BEND noncore/unsupported/mail2/bend bend.pro
CONFIG_BIGSCREEN_EXAMPLE unsupported/libopie/big-screen/example osplitter_mail.pro
CONFIG_BLUE-PIN noncore/net/opietooth/blue-pin blue-pin.pro
CONFIG_BOUNCE noncore/games/bounce bounce.pro
CONFIG_BRIGHTNESSAPPLET noncore/applets/brightnessapplet brightnessapplet.pro
CONFIG_BUTTON-SETTINGS core/settings/button button.pro
CONFIG_BUZZWORD noncore/games/buzzword buzzword.pro
CONFIG_CALC2 noncore/tools/calc2 calc2.pro
CONFIG_CALCULATOR noncore/tools/calculator calculator.pro
CONFIG_CALIBRATE core/apps/calibrate calibrate.pro
CONFIG_CAMERA noncore/multimedia/camera camera.pro
+CONFIG_CAMERA2 noncore/multimedia/camera2 camera2.pro
CONFIG_CARDMON core/applets/cardmon cardmon.pro
CONFIG_CHECKBOOK noncore/apps/checkbook checkbook.pro
CONFIG_CITYTIME core/settings/citytime citytime.pro
CONFIG_CLIPBOARDAPPLET core/applets/clipboardapplet clipboardapplet.pro
CONFIG_CLOCKAPPLET core/applets/clockapplet clockapplet.pro
CONFIG_CLOCK noncore/tools/clock clock.pro
CONFIG_CONFEDIT noncore/apps/confedit confedit.pro
CONFIG_DAGGER noncore/apps/dagger dagger.pro
CONFIG_DASHER inputmethods/dasher dasher.pro
CONFIG_DATEBOOK2 core/pim/datebook2 datebook2.pro
CONFIG_DATEBOOK core/pim/datebook datebook.pro
CONFIG_DATEBOOK_BIRTHDAYS_HOLIDAY core/pim/datebook/holiday/birthday birthdays.pro
CONFIG_DATEBOOK_CHRISTIAN_HOLIDAY core/pim/datebook/holiday/christian christian-holidays.pro
CONFIG_DATEBOOK_NATIONAL_HOLIDAY core/pim/datebook/holiday/national national-holidays.pro
CONFIG_DECO_FLAT noncore/decorations/flat flat.pro
CONFIG_DECO_LIQUID noncore/decorations/liquid liquid.pro
CONFIG_DECO_POLISHED noncore/decorations/polished polished.pro
CONFIG_DICTIONARY noncore/apps/dictionary dictionary.pro
CONFIG_DOCTAB noncore/settings/doctab doctab.pro
CONFIG_DRAWPAD noncore/graphics/drawpad drawpad.pro
CONFIG_DVORAK inputmethods/dvorak dvorak.pro
CONFIG_EMBEDDEDKONSOLE core/apps/embeddedkonsole embeddedkonsole.pro
CONFIG_EUROCONV noncore/tools/euroconv/ euroconv.pro
CONFIG_EXAMPLE_APPLET examples/applet applet.pro
CONFIG_EXAMPLE_BOARD examples/inputmethod inputmethod.pro
CONFIG_EXAMPLE_LIBOPIE2BLUEZ examples/opiebluez opiebluez.pro
CONFIG_EXAMPLE_LIBOPIE2CORE examples/opiecore opiecore.pro
CONFIG_EXAMPLE_LIBOPIE2DB examples/opiedb opiedb.pro
CONFIG_EXAMPLE_LIBOPIE2MM examples/opiemm opiemm.pro
CONFIG_EXAMPLE_LIBOPIE2NET examples/opienet opienet.pro
CONFIG_EXAMPLE_LIBOPIE2PIM examples/opiepim opiepim.pro
CONFIG_EXAMPLE_LIBOPIE2SECURITY examples/opiesecurity opiesecurity.pro
CONFIG_EXAMPLE_LIBOPIE2UI examples/opieui opieui.pro
CONFIG_EXAMPLE_MENU examples/menuapplet menuapplet.pro
CONFIG_EXAMPLE_VPN examples/networksettings networksettings.pro
CONFIG_FIFTEEN noncore/games/fifteen fifteen.pro
CONFIG_FILEBROWSER noncore/unsupported/filebrowser filebrowser.pro
CONFIG_FLAT noncore/styles/flat flat.pro
CONFIG_FORMATTER noncore/tools/formatter formatter.pro
CONFIG_FREETYPE freetype freetype.pro
CONFIG_FRESH noncore/styles/fresh fresh.pro
CONFIG_FTPLIB noncore/net/ftplib ftplib.pro
CONFIG_GO noncore/games/go go.pro
CONFIG_GSMTOOL noncore/unsupported/gsmtool gsmtool.pro
CONFIG_GUTENBROWSER noncore/apps/opie-gutenbrowser opie-gutenbrowser.pro
CONFIG_HANDWRITING inputmethods/handwriting handwriting.pro
CONFIG_HELPBROWSER core/apps/helpbrowser helpbrowser.pro
CONFIG_HOMEAPPLET core/applets/homeapplet homeapplet.pro
CONFIG_HOTPLUG_QCOP core/tools/hotplug-qcop hotplug-qcop.pro
CONFIG_INTERFACES noncore/settings/networksettings/interfaces interfaces.pro
CONFIG_IRDAAPPLET core/applets/irdaapplet irdaapplet.pro
CONFIG_JUMPX inputmethods/jumpx jumpx.pro
CONFIG_KBILL noncore/games/kbill kbill.pro
CONFIG_KCHECKERS noncore/games/kcheckers kcheckers.pro
CONFIG_KEYBOARD inputmethods/keyboard keyboard.pro
CONFIG_KEYHELPER noncore/applets/keyhelper keyhelper.pro
CONFIG_KEYPEBBLE noncore/comm/keypebble keypebble.pro
CONFIG_KEYVIEW development/keyview keyview.pro
CONFIG_KJUMPX inputmethods/kjumpx kjumpx.pro
CONFIG_KPACMAN noncore/games/kpacman kpacman.pro
CONFIG_LANGUAGE noncore/settings/language language.pro
CONFIG_LAUNCHER core/launcher server.pro
CONFIG_LAUNCHER-SETTINGS core/settings/launcher launcher.pro
CONFIG_LIBFFMPEG core/multimedia/opieplayer/libffmpeg libffmpeg.pro
CONFIG_LIBFLASH core/multimedia/opieplayer/libflash libflash.pro
CONFIG_LIBMAD core/multimedia/opieplayer/libmad libmad.pro
CONFIG_LIBMAIL noncore/unsupported/mail2/libmail libmail.pro
CONFIG_LIBMAILWRAPPER noncore/net/mail/libmailwrapper libmailwrapper.pro
CONFIG_LIBMPEG3 core/multimedia/opieplayer/libmpeg3 libmpeg3.pro
CONFIG_LIBOPIE2BLUEZ libopie2/opiebluez opiebluez.pro
CONFIG_LIBOPIE2CORE libopie2/opiecore opiecore.pro
CONFIG_LIBOPIE2DB libopie2/opiedb opiedb.pro
CONFIG_LIBOPIE2EXAMPLES libopie2/examples examples.pro
CONFIG_LIBOPIE2MM libopie2/opiemm opiemm.pro
CONFIG_LIBOPIE2NET libopie2/opienet opienet.pro
CONFIG_LIBOPIE2PIM libopie2/opiepim opiepim.pro
CONFIG_LIBOPIE2SECURITY libopie2/opiesecurity opiesecurity.pro
CONFIG_LIBOPIE2UI libopie2/opieui opieui.pro
CONFIG_LIBOPIETOOTH noncore/net/opietooth/lib lib.pro
CONFIG_LIBOPIE noncore/unsupported/libopie libopie.pro
CONFIG_LIBQPE library library.pro
CONFIG_LIBQPE-X11 x11/libqpe-x11 libqpe-x11.pro
CONFIG_LIBQRSYNC rsync rsync.pro
CONFIG_LIBQTAUX libqtaux libqtaux.pro
CONFIG_LIBSQL libsql libsql.pro
CONFIG_LIBTREMOR core/multimedia/opieplayer/vorbis/tremor tremor.pro
CONFIG_LIBTREMORPLUGIN core/multimedia/opieplayer/vorbis libtremor.pro
CONFIG_LIGHT-AND-POWER core/settings/light-and-power light-and-power.pro
CONFIG_LIQUID noncore/styles/liquid liquid.pro
CONFIG_LOCKAPPLET core/applets/lockapplet lockapplet.pro
CONFIG_LOGOUTAPPLET core/applets/logoutapplet logoutapplet.pro
CONFIG_MAIL3 noncore/net/mail mail.pro
CONFIG_MAILAPPLET noncore/net/mail/taskbarapplet taskbarapplet.pro
CONFIG_MAILIT noncore/unsupported/mailit mailit.pro
CONFIG_MAIN_TAB_EXAMPLE examples/main-tab main-tab.pro
CONFIG_MEDIUMMOUNT noncore/settings/mediummount mediummount.pro
CONFIG_MEMORYAPPLET noncore/applets/memoryapplet memoryapplet.pro
CONFIG_METAL noncore/styles/metal metal.pro
CONFIG_MINDBREAKER noncore/games/mindbreaker mindbreaker.pro
CONFIG_MINESWEEP noncore/games/minesweep minesweep.pro
CONFIG_MOBILEMSG noncore/unsupported/mobilemsg mobilemsg.pro
CONFIG_MODPLUG core/multimedia/opieplayer/modplug modplug.pro
CONFIG_MULTIAUTH_BLUEPING noncore/securityplugins/blueping bluepingplugin.pro
CONFIG_MULTIAUTH_DUMMY noncore/securityplugins/dummy dummyplugin.pro
CONFIG_MULTIAUTH_NOTICE noncore/securityplugins/notice noticeplugin.pro
CONFIG_MULTIAUTH_PIN noncore/securityplugins/pin pinplugin.pro
CONFIG_MULTIKEYAPPLET core/applets/multikeyapplet multikeyapplet.pro
CONFIG_MULTIKEY inputmethods/multikey multikey.pro
CONFIG_NETSYSTEMTIME noncore/settings/netsystemtime netsystemtime.pro
CONFIG_NETWORKAPPLET noncore/applets/networkapplet networkapplet.pro
CONFIG_NETWORKSETUP noncore/settings/networksettings networksettings.pro
CONFIG_NOTES core/pim/notes opie-notes.pro
CONFIG_NOTESAPPLET noncore/applets/notesapplet notesapplet.pro
CONFIG_NS2BT noncore/settings/networksettings2/bluetooth bluetooth.pro
CONFIG_NS2GPRS noncore/settings/networksettings2/gprs GPRS.pro
CONFIG_NS2CABLE noncore/settings/networksettings2/cable cable.pro
CONFIG_NS2CORE noncore/settings/networksettings2/networksettings2 networksettings2.pro
CONFIG_NS2OPIETOOTH noncore/settings/networksettings2/opietooth2 opietooth2.pro
CONFIG_NS2OPIETOOTHAPPLET noncore/settings/networksettings2/opietooth2_applet opietooth2_applet.pro
CONFIG_NS2IRDA noncore/settings/networksettings2/irda irda.pro
CONFIG_NS2LANCARD noncore/settings/networksettings2/lancard lancard.pro
CONFIG_NS2MODEM noncore/settings/networksettings2/modem modem.pro
CONFIG_NS2NETWORK noncore/settings/networksettings2/network network.pro
CONFIG_NS2 noncore/settings/networksettings2 networksettings.pro
CONFIG_NS2PPP noncore/settings/networksettings2/ppp ppp.pro
CONFIG_NS2PROFILE noncore/settings/networksettings2/profile profile.pro
CONFIG_NS2USB noncore/settings/networksettings2/usb usb.pro
CONFIG_NS2VPN noncore/settings/networksettings2/vpn vpn.pro
CONFIG_NS2WLAN noncore/settings/networksettings2/wlan wlan.pro
CONFIG_OAPP core/apps/oapp oapp.pro
CONFIG_OBEX core/obex obex.pro
CONFIG_ODICT noncore/apps/odict odict.pro
CONFIG_OIPKG noncore/unsupported/oipkg oipkg.pro
CONFIG_OPIEALARM core/opiealarm opiealarm.pro
CONFIG_OPIE-CONSOLE noncore/apps/opie-console opie-console.pro
CONFIG_OPIE_EYE noncore/graphics/opie-eye phunk_view.pro
CONFIG_OPIE_EYE_SLAVE noncore/graphics/opie-eye/slave slave.pro
CONFIG_OPIEFTP noncore/net/opieftp opieftp.pro
CONFIG_OPIEIRC noncore/net/opieirc opieirc.pro
CONFIG_OPIE-LOGIN core/opie-login opie-login.pro
CONFIG_OPIEMAIL2 noncore/unsupported/mail2 mail.pro
CONFIG_OPIEPLAYER2 noncore/multimedia/opieplayer2 opieplayer2.pro
CONFIG_OPIEPLAYER3 noncore/multimedia/opieplayer3 opieplayer3.pro
CONFIG_OPIEPLAYER core/multimedia/opieplayer opieplayer.pro
CONFIG_OPIE-RDESKTOP noncore/net/opierdesktop opierdesktop.pro
CONFIG_OPIE-READER noncore/apps/opie-reader opie-reader.pro
CONFIG_OPIE-READER-FLITEDYN noncore/apps/opie-reader/FliteDyn FliteDyn.pro
CONFIG_OPIE-READER-FLITEDYN16 noncore/apps/opie-reader/FliteDyn16 FliteDyn16.pro
CONFIG_OPIEREC noncore/multimedia/opierec opierec.pro
CONFIG_OPIESMB noncore/net/opie-smb opie-smb.pro
CONFIG_OPIE-SHEET noncore/apps/opie-sheet opie-sheet.pro
CONFIG_OPIE-SH noncore/tools/opie-sh opie-sh.pro
CONFIG_OPIETOOTH-APPLET noncore/net/opietooth/applet applet.pro
CONFIG_OPIETOOTH-MANAGER noncore/net/opietooth/manager manager.pro
CONFIG_OPIE-WRITE noncore/apps/opie-write opie-write.pro
CONFIG_OSEARCH core/pim/osearch osearch.pro
CONFIG_OXYGEN noncore/apps/oxygen oxygen.pro
CONFIG_PACKAGEMANAGER noncore/settings/packagemanager packagemanager.pro
CONFIG_PARASHOOT noncore/games/parashoot parashoot.pro
CONFIG_PCMCIA-APPLET noncore/applets/pcmcia pcmcia.pro
CONFIG_PHASE noncore/styles/phase phase.pro
CONFIG_PICKBOARD inputmethods/pickboard pickboard.pro
CONFIG_PIMCONVERTER noncore/tools/pimconverter converter.pro
CONFIG_POWERCHORD noncore/multimedia/powerchord powerchord.pro
CONFIG_PPP noncore/settings/networksettings/ppp ppp.pro
CONFIG_PYQUICKLAUNCH-APPLET noncore/applets/pyquicklaunch pyquicklaunch.pro
CONFIG_PYQUICKLAUNCHER noncore/tools/pyquicklauncher pyquicklauncher.pro
CONFIG_PYTHON-EXAMPLES examples/python bla.pro
CONFIG_QASHMONEY noncore/unsupported/qashmoney qashmoney.pro
CONFIG_QASTEROIDS noncore/games/qasteroids qasteroids.pro
CONFIG_QCOP core/apps/qcop qcop.pro
CONFIG_QPDF noncore/unsupported/qpdf qpdf.pro
CONFIG_QSS core/apps/qss qss.pro
CONFIG_QUICKLAUNCHER core/tools/quicklauncher quicklauncher.pro
CONFIG_QWS core/qws qws.pro
CONFIG_REMOTE noncore/tools/remote remote.pro
CONFIG_RESTARTAPPLET2 core/applets/restartapplet2 restartapplet2.pro
CONFIG_RESTARTAPPLET core/applets/restartapplet restartapplet.pro
CONFIG_ROTATEAPPLET core/applets/rotateapplet rotateapplet.pro
CONFIG_ROTATION noncore/settings/rotation rotation.pro
CONFIG_RUNAPPLET core/applets/runapplet runapplet.pro
CONFIG_SCREENSHOTAPPLET core/applets/screenshotapplet screenshotapplet.pro
CONFIG_SECURITY core/settings/security security.pro
CONFIG_MULTIAUTH_DEMO core/settings/security/demo multiauth.pro
CONFIG_SFCAVE noncore/games/sfcave sfcave.pro
CONFIG_SFCAVE-SDL noncore/games/sfcave-sdl sfcave-sdl.pro
CONFIG_SHOWIMG noncore/unsupported/showimg showimg.pro
CONFIG_SIMPLE_EXAMPLE examples/simple simple.pro
CONFIG_SIMPLE_ICON examples/simple-icon simple-icon.pro
CONFIG_SIMPLE_MAIN examples/simple-main simple-main.pro
CONFIG_SIMPLE_PIM examples/simple-pim simple-pim.pro
CONFIG_SINGLE single single.pro
CONFIG_SNAKE noncore/games/snake snake.pro
CONFIG_SOLITAIRE noncore/games/solitaire solitaire.pro
CONFIG_SOUND noncore/settings/sound sound.pro
CONFIG_SSHKEYS noncore/settings/sshkeys sshkeys.pro
CONFIG_SUSPENDAPPLET core/applets/suspendapplet suspendapplet.pro
CONFIG_SYMLINKER core/symlinker symlinker.pro
CONFIG_SYSINFO noncore/settings/sysinfo sysinfo.pro
CONFIG_TABLEVIEWER noncore/apps/tableviewer tableviewer.pro
CONFIG_TABMANAGER noncore/unsupported/tabmanager tabmanager.pro
CONFIG_TABOAPP core/apps/taboapp taboapp.pro
CONFIG_TEST libsql/test test.pro
CONFIG_TEST noncore/apps/opie-console/test test.pro
CONFIG_TETRIX noncore/games/tetrix tetrix.pro
CONFIG_TEXTEDIT core/apps/textedit textedit.pro
CONFIG_THEME noncore/styles/theme theme.pro
CONFIG_TICTAC noncore/games/tictac tictac.pro
CONFIG_TINYKATE noncore/apps/tinykate tinykate.pro
CONFIG_TODAY_ADDRESSBOOK core/pim/today/plugins/addressbook addressbook.pro
CONFIG_TODAY core/pim/today today.pro
CONFIG_TODAY_DATEBOOK core/pim/today/plugins/datebook datebook.pro
CONFIG_TODAY_EXAMPLE examples/todayplugin todayplugin.pro
CONFIG_TODAY_FORTUNE noncore/todayplugins/fortune fortune.pro
CONFIG_TODAY_MAIL core/pim/today/plugins/mail mail.pro
CONFIG_TODAY_STOCKTICKERLIB noncore/todayplugins/stockticker/stocktickerlib stocktickerlib.pro
CONFIG_TODAY_STOCKTICKER noncore/todayplugins/stockticker/stockticker stockticker.pro
CONFIG_TODAY_TODOLIST core/pim/today/plugins/todolist todolist.pro
CONFIG_TODAY_WEATHER noncore/todayplugins/weather weather.pro
CONFIG_TODO core/pim/todo todo.pro
CONFIG_TONLEITER noncore/multimedia/tonleiter tonleiter.pro
CONFIG_TRACKER noncore/multimedia/tracker tracker.pro
CONFIG_UBROWSER noncore/unsupported/ubrowser ubrowser.pro
CONFIG_UNIKEYBOARD inputmethods/unikeyboard unikeyboard.pro
CONFIG_USERMANAGER noncore/settings/usermanager usermanager.pro
CONFIG_VMEMO core/applets/vmemo vmemo.pro
CONFIG_VOLUMEAPPLET core/applets/volumeapplet volumeapplet.pro
CONFIG_VOLUMEAPPLET2 noncore/applets/volumeapplet2 volumeapplet2.pro
CONFIG_VTAPPLET core/applets/vtapplet vtapplet.pro
CONFIG_WAVPLUGIN core/multimedia/opieplayer/wavplugin wavplugin.pro
CONFIG_WEBSTYLE noncore/styles/web web.pro
CONFIG_WELLENREITER noncore/net/wellenreiter wellenreiter.pro
CONFIG_WIRELESSAPPLET noncore/applets/wirelessapplet wirelessapplet.pro
CONFIG_WLAN noncore/settings/networksettings/wlan wlan.pro
CONFIG_WORDGAME noncore/games/wordgame wordgame.pro
CONFIG_YATZEE noncore/games/oyatzee oyatzee.pro
CONFIG_ZKBAPPLET noncore/applets/zkbapplet zkbapplet.pro
CONFIG_ZLINES noncore/games/zlines zlines.pro
CONFIG_ZSAFE noncore/apps/zsafe zsafe.pro
CONFIG_ZSAME noncore/games/zsame zsame.pro
CONFIG_OPIESTUMBLER noncore/net/opiestumbler opiestumbler.pro
diff --git a/pics/camera2/Camera.png b/pics/camera2/Camera.png
new file mode 100644
index 0000000..e619c11
--- a/dev/null
+++ b/pics/camera2/Camera.png
Binary files differ
diff --git a/pics/camera2/Camera_48.png b/pics/camera2/Camera_48.png
new file mode 100644
index 0000000..00b8585
--- a/dev/null
+++ b/pics/camera2/Camera_48.png
Binary files differ
diff --git a/pics/camera2/Camera_48_anim.mng b/pics/camera2/Camera_48_anim.mng
new file mode 100644
index 0000000..6b19394
--- a/dev/null
+++ b/pics/camera2/Camera_48_anim.mng
Binary files differ
diff --git a/pics/camera2/settings.png b/pics/camera2/settings.png
new file mode 100644
index 0000000..05bfdf7
--- a/dev/null
+++ b/pics/camera2/settings.png
Binary files differ