author | eilers <eilers> | 2003-11-03 16:52:18 (UTC) |
---|---|---|
committer | eilers <eilers> | 2003-11-03 16:52:18 (UTC) |
commit | d34dc773591a2d467c68875a68a671d6a809f861 (patch) (side-by-side diff) | |
tree | b57e5ae15c51e3d87ca95d57aedfd1ca3db57bfe /library | |
parent | ce84f2d8bdd65c438821f0457cdad6bbbfa73380 (diff) | |
download | opie-d34dc773591a2d467c68875a68a671d6a809f861.zip opie-d34dc773591a2d467c68875a68a671d6a809f861.tar.gz opie-d34dc773591a2d467c68875a68a671d6a809f861.tar.bz2 |
Porting Opie to MacOS-X.
The base system and all platform independent applications and platforms
should work.
Please see $OPIEDIR/development/macosx for details
-rw-r--r-- | library/filemanager.cpp | 43 | ||||
-rw-r--r-- | library/fontdatabase.cpp | 4 | ||||
-rw-r--r-- | library/global.cpp | 4 | ||||
-rw-r--r-- | library/library.pro | 2 | ||||
-rw-r--r-- | library/network.cpp | 4 | ||||
-rw-r--r-- | library/qlibrary_unix.cpp | 113 | ||||
-rw-r--r-- | library/qpeapplication.cpp | 29 | ||||
-rw-r--r-- | library/qpedecoration_qws.cpp | 8 | ||||
-rw-r--r-- | library/sound.cpp | 3 | ||||
-rw-r--r-- | library/storage.cpp | 36 |
10 files changed, 240 insertions, 6 deletions
diff --git a/library/filemanager.cpp b/library/filemanager.cpp index cc657fa..91986a0 100644 --- a/library/filemanager.cpp +++ b/library/filemanager.cpp @@ -1,341 +1,384 @@ /********************************************************************** ** 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. ** **********************************************************************/ #include "filemanager.h" #include "applnk.h" #include <qdir.h> #include <qfile.h> #include <qfileinfo.h> #include <qtextstream.h> #include <qtextcodec.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <dirent.h> +#ifdef Q_OS_MACX +// MacOS X does not have sendfile.. :( +// But maybe in the future.. !? +# ifdef SENDFILE +# include <sys/types.h> +# include <sys/socket.h> +# endif +#else #include <sys/sendfile.h> +#endif /* Q_OS_MACX */ #include <fcntl.h> /*! \class FileManager \brief The FileManager class assists with AppLnk input/output. */ /*! Constructs a FileManager. */ FileManager::FileManager() { } /*! Destroys a FileManager. */ FileManager::~FileManager() { } /*! Saves \a data as the document specified by \a f. Returns whether the operation succeeded. */ bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) { QString fn = f.file() + ".new"; ensurePathExists( fn ); QFile fl( fn ); if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { qWarning("open failed"); return FALSE; } int total_written = fl.writeBlock( data ); fl.close(); if ( total_written != int(data.size()) || !f.writeLink() ) { QFile::remove( fn ); return FALSE; } qDebug("total written %d out of %d", total_written, data.size()); // else rename the file... if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), f.file().latin1(), errno ); // remove the file... } return TRUE; } /*! Saves \a text as the document specified by \a f. The text is saved in UTF8 format. Returns whether the operation succeeded. */ bool FileManager::saveFile( const DocLnk &f, const QString &text ) { QString fn = f.file() + ".new"; ensurePathExists( fn ); QFile fl( fn ); if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { qWarning("open failed"); return FALSE; } QCString cstr = text.utf8(); int total_written; total_written = fl.writeBlock( cstr.data(), cstr.length() ); fl.close(); if ( total_written != int(cstr.length()) || !f.writeLink() ) { QFile::remove( fn ); return FALSE; } // okay now rename the file.. if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), f.file().latin1(), errno ); } return TRUE; } /*! Loads \a text from the document specified by \a f. The text is required to be in UTF8 format. Returns whether the operation succeeded. */ bool FileManager::loadFile( const DocLnk &f, QString &text ) { QString fn = f.file(); QFile fl( fn ); if ( !fl.open( IO_ReadOnly ) ) return FALSE; QTextStream ts( &fl ); #if QT_VERSION <= 230 && defined(QT_NO_CODECS) // The below should work, but doesn't in Qt 2.3.0 ts.setCodec( QTextCodec::codecForMib( 106 ) ); #else ts.setEncoding( QTextStream::UnicodeUTF8 ); #endif text = ts.read(); fl.close(); return TRUE; } /*! Loads \a ba from the document specified by \a f. Returns whether the operation succeeded. */ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba ) { QString fn = f.file(); QFile fl( fn ); if ( !fl.open( IO_ReadOnly ) ) return FALSE; ba.resize( fl.size() ); if ( fl.size() > 0 ) fl.readBlock( ba.data(), fl.size() ); fl.close(); return TRUE; } /*! Copies the document specified by \a src to the document specified by \a dest. Returns whether the operation succeeded. */ bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest ) { QFile sf( src.file() ); if ( !sf.open( IO_ReadOnly ) ) return FALSE; QString fn = dest.file() + ".new"; ensurePathExists( fn ); QFile df( fn ); if ( !df.open( IO_WriteOnly|IO_Raw ) ) return FALSE; const int bufsize = 16384; char buffer[bufsize]; bool ok = TRUE; int bytesRead = 0; while ( ok && !sf.atEnd() ) { bytesRead = sf.readBlock( buffer, bufsize ); if ( bytesRead < 0 ) ok = FALSE; while ( ok && bytesRead > 0 ) { int bytesWritten = df.writeBlock( buffer, bytesRead ); if ( bytesWritten < 0 ) ok = FALSE; else bytesRead -= bytesWritten; } } if ( ok ) ok = dest.writeLink(); if ( ok ) { // okay now rename the file... if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) { qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), dest.file().latin1(), errno ); // remove the tmp file, otherwise, it will just lay around... QFile::remove( fn.latin1() ); } } else { QFile::remove( fn.latin1() ); } return ok; } + + bool FileManager::copyFile( const QString & src, const QString & dest ) { bool success = true; struct stat status; int read_fd=0; int write_fd=0; struct stat stat_buf; off_t offset = 0; QFile srcFile(src); QFile destFile(dest); if(!srcFile.open( IO_ReadOnly|IO_Raw)) { return success = false; } read_fd = srcFile.handle(); if(read_fd != -1) { fstat (read_fd, &stat_buf); if( !destFile.open( IO_WriteOnly|IO_Raw ) ) return success = false; write_fd = destFile.handle(); if(write_fd != -1) { int err=0; QString msg; +#ifdef Q_OS_MACX +#ifdef SENDMAIL + /* FreeBSD does support a different kind of + * sendfile. (eilers) + * I took this from Very Secure FTPd + * Licence: GPL + * Author: Chris Evans + * sysdeputil.c + */ + /* XXX - start_pos will truncate on 32-bit machines - can we + * say "start from current pos"? + */ + off_t written = 0; + int retval = 0; + retval = sendfile(read_fd, write_fd, offset, stat_buf.st_size, NULL, + &written, 0); + /* Translate to Linux-like retval */ + if (written > 0) + { + err = (int) written; + } +#else /* SENDMAIL */ + err == -1; + msg = "FAILURE: Using unsupported function \"sendfile()\" Need Workaround !!"; + success = false; +# warning "Need workaround for sendfile!!(eilers)" +#endif /* SENDMAIL */ + +#else err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size); if( err == -1) { switch(err) { case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. "; case EINVAL: msg = "Descriptor is not valid or locked. "; case ENOMEM: msg = "Insufficient memory to read from in_fd."; case EIO: msg = "Unspecified error while reading from in_fd."; }; success = false; } +#endif /* Q_OS_MACX */ + if( !success ) + qWarning( msg ); } else { qWarning("open write failed %s, %s",src.latin1(), dest.latin1()); success = false; } } else { qWarning("open read failed %s, %s",src.latin1(), dest.latin1()); success = false; } srcFile.close(); destFile.close(); // Set file permissions if( stat( (const char *) src, &status ) == 0 ) { chmod( (const char *) dest, status.st_mode ); } return success; } bool FileManager::renameFile( const QString & src, const QString & dest ) { if(copyFile( src, dest )) { if(QFile::remove(src) ) { return true; } } return false; } /*! Opens the document specified by \a f as a readable QIODevice. The caller must delete the return value. Returns 0 if the operation fails. */ QIODevice* FileManager::openFile( const DocLnk& f ) { QString fn = f.file(); QFile* fl = new QFile( fn ); if ( !fl->open( IO_ReadOnly ) ) { delete fl; fl = 0; } return fl; } /*! Opens the document specified by \a f as a writable QIODevice. The caller must delete the return value. Returns 0 if the operation fails. */ QIODevice* FileManager::saveFile( const DocLnk& f ) { QString fn = f.file(); ensurePathExists( fn ); QFile* fl = new QFile( fn ); if ( fl->open( IO_WriteOnly ) ) { f.writeLink(); } else { delete fl; fl = 0; } return fl; } /*! Returns whether the document specified by \a f current exists as a file on disk. */ bool FileManager::exists( const DocLnk &f ) { return QFile::exists(f.file()); } /*! Ensures that the path \a fn exists, by creating required directories. Returns TRUE if successful. */ bool FileManager::ensurePathExists( const QString &fn ) { QFileInfo fi(fn); fi.setFile( fi.dirPath(TRUE) ); if ( !fi.exists() ) { if ( system(("mkdir -p "+fi.filePath())) ) return FALSE; } return TRUE; } diff --git a/library/fontdatabase.cpp b/library/fontdatabase.cpp index c7a5211..2ad8e95 100644 --- a/library/fontdatabase.cpp +++ b/library/fontdatabase.cpp @@ -45,205 +45,209 @@ static QString fontFamily( const QString& key ) int u2 = key.find('_',u1+1); QString family = key.left(u0); //int pointSize = key.mid(u0+1,u1-u0-1).toInt(); //int weight = key.mid(u1+1,u2-u1-1).toInt(); //bool italic = key.mid(u2-1,1) == "i"; // #### ignores _t and _I fields return family; } #endif QValueList<FontFactory> *FontDatabase::factoryList = 0; /*! \class FontDatabase fontdatabase.h \brief The FontDatabase class provides information about available fonts. Most often you will simply want to query the database for the available font families(). Use FontDatabase rather than QFontDatabase when you may need access to fonts that are not normally available. For example, if the freetype library and the Qtopia freetype plugin are installed, TrueType fonts will be available to your application. Font renderer plugins have greater resource requirements than system fonts so they should be used only when necessary. You can force the loading of font renderer plugins with loadRenderers(). \ingroup qtopiaemb */ /*! Constructs a FontDatabase object. */ FontDatabase::FontDatabase() #ifndef QT_NO_FONTDATABASE : QFontDatabase() #endif { if ( !factoryList ) loadRenderers(); } /*! Returns a list of names of all the available font families. */ QStringList FontDatabase::families() const { #ifndef QT_NO_FONTDATABASE return QFontDatabase::families(); #else #ifndef QWS QStringList list; return list; #else QStringList list; QDict<void> familyDict; QDiskFont *qdf; for ( qdf=qt_fontmanager->diskfonts.first(); qdf!=0; qdf=qt_fontmanager->diskfonts.next()) { QString familyname = qdf->name; if ( !familyDict.find( familyname ) ) { familyDict.insert( familyname, (void *)1 ); list.append( familyname ); } } QDir dir(fontDir(),"*.qpf"); for (int i=0; i<(int)dir.count(); i++) { QString familyname = fontFamily(dir[i]); if ( !familyDict.find( familyname ) ) { familyDict.insert( familyname, (void *)1 ); list.append( familyname ); } } return list; #endif #endif } #ifdef QT_NO_FONTDATABASE /*! Returns a list of standard fontsizes. */ QValueList<int> FontDatabase::standardSizes() { static int s[]={ 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72, 0 }; static bool first = TRUE; static QValueList<int> sList; if ( first ) { first = FALSE; int i = 0; while( s[i] ) sList.append( s[i++] ); } return sList; } #endif /*! Load any font renderer plugins that are available and make the fonts that the plugins can read available. */ void FontDatabase::loadRenderers() { #ifndef QWS return; #else #ifndef QT_NO_COMPONENT if ( !factoryList ) factoryList = new QValueList<FontFactory>; QValueList<FontFactory>::Iterator mit; for ( mit = factoryList->begin(); mit != factoryList->end(); ++mit ) { qt_fontmanager->factories.setAutoDelete( false ); qt_fontmanager->factories.removeRef( (*mit).factory ); qt_fontmanager->factories.setAutoDelete( true ); (*mit).interface->release(); (*mit).library->unload(); delete (*mit).library; } factoryList->clear(); QString path = QPEApplication::qpeDir() + "/plugins/fontfactories"; +#ifdef Q_OS_MACX + QDir dir( path, "lib*.dylib" ); +#else QDir dir( path, "lib*.so" ); +#endif if ( !dir.exists()) return; QStringList list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { FontFactoryInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_FontFactory, (QUnknownInterface**)&iface ) == QS_OK ) { FontFactory factory; factory.library = lib; factory.interface = iface; factory.factory = factory.interface->fontFactory(); factoryList->append( factory ); qt_fontmanager->factories.append( factory.factory ); readFonts( factory.factory ); } else { delete lib; } } #endif #endif } /*! \internal */ void FontDatabase::readFonts( QFontFactory *factory ) { #ifndef QWS return; #else // Load in font definition file QString fn = fontDir() + "fontdir"; FILE* fontdef=fopen(fn.local8Bit(),"r"); if(!fontdef) { QCString temp=fn.local8Bit(); qWarning("Cannot find font definition file %s - is $QTDIR set correctly?", temp.data()); return; } char buf[200]=""; char name[200]=""; char render[200]=""; char file[200]=""; char flags[200]=""; char isitalic[10]=""; fgets(buf,200,fontdef); while(!feof(fontdef)) { if ( buf[0] != '#' ) { int weight=50; int size=0; flags[0]=0; sscanf(buf,"%s %s %s %s %d %d %s",name,file,render,isitalic,&weight,&size,flags); QString filename; if ( file[0] != '/' ) filename = fontDir(); filename += file; if ( QFile::exists(filename) ) { if( factory->name() == render ) { QDiskFont * qdf=new QDiskFont(factory,name,isitalic[0]=='y', weight,size,flags,filename); qt_fontmanager->diskfonts.append(qdf); #if QT_VERSION >= 232 QFontDatabase::qwsAddDiskFont( qdf ); #endif } } } fgets(buf,200,fontdef); } fclose(fontdef); #endif } diff --git a/library/global.cpp b/library/global.cpp index 90954fe..05d23ac 100644 --- a/library/global.cpp +++ b/library/global.cpp @@ -479,257 +479,261 @@ bool Global::isBuiltinCommand( const QString &name ) } 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; } diff --git a/library/library.pro b/library/library.pro index ab1f451..5acfc0c 100644 --- a/library/library.pro +++ b/library/library.pro @@ -1,157 +1,157 @@ 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 \ qt_override_p.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 \ qt_override.cpp # Qt 3 compatibility HEADERS += quuid.h qcom.h qlibrary.h qlibrary_p.h SOURCES += quuid.cpp qlibrary.cpp qlibrary_unix.cpp INCLUDEPATH += $(OPIEDIR)/include backend -LIBS += -ldl -lcrypt -lm +# 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 TRANSLATIONS = ../i18n/de/libqpe.ts \ ../i18n/nl/libqpe.ts \ ../i18n/xx/libqpe.ts \ ../i18n/en/libqpe.ts \ ../i18n/es/libqpe.ts \ ../i18n/fr/libqpe.ts \ ../i18n/hu/libqpe.ts \ ../i18n/ja/libqpe.ts \ ../i18n/ko/libqpe.ts \ ../i18n/no/libqpe.ts \ ../i18n/pl/libqpe.ts \ ../i18n/pt/libqpe.ts \ ../i18n/pt_BR/libqpe.ts \ ../i18n/sl/libqpe.ts \ ../i18n/zh_CN/libqpe.ts \ ../i18n/it/libqpe.ts \ ../i18n/zh_TW/libqpe.ts \ ../i18n/da/libqpe.ts include ( $(OPIEDIR)/include.pro ) contains( CONFIG, no-override ){ DEFINES += OPIE_NO_OVERRIDE_QT } diff --git a/library/network.cpp b/library/network.cpp index 3568809..991e11a 100644 --- a/library/network.cpp +++ b/library/network.cpp @@ -293,152 +293,156 @@ private: startTimer(400); stopped = TRUE; } } } if ( !stopped ) { QCopEnvelope("QPE/Network", "failed()"); } } void timerEvent(QTimerEvent*) { examineNetworks(); if ( wait >= 0 ) { if ( up == !current.isNull() ) { // done killTimers(); if ( up ) { startTimer(3000); // monitor link wait = -1; } } else { wait++; if ( wait == 600 ) { killTimers(); // forget about it after 240 s QCopEnvelope("QPE/Network", "failed()"); up = !current.isNull(); } } } else if ( !up ) { killTimers(); } } private: QStringList available; QString current; bool up; int wait; }; static NetworkServer* ns=0; /*! \internal */ QString Network::serviceName(const QString& service) { Config cfg(service, Config::File); cfg.setGroup("Info"); return cfg.readEntry("Name"); } /*! \internal */ QString Network::serviceType(const QString& service) { Config cfg(service, Config::File); cfg.setGroup("Info"); return cfg.readEntry("Type"); } /*! \internal */ bool Network::serviceNeedsPassword(const QString& service) { Config cfg(service,Config::File); cfg.setGroup("Info"); QString type = cfg.readEntry("Type"); NetworkInterface* plugin = Network::loadPlugin(type); cfg.setGroup("Properties"); return plugin ? plugin->needPassword(cfg) : FALSE; } /*! \internal */ bool Network::networkOnline() { return ns && ns->networkOnline(); } /*! \internal */ void Network::createServer(QObject* parent) { ns = new NetworkServer(parent); } /*! \internal */ int Network::addStateWidgets(QWidget* parent) { int n=0; QStringList l = Network::choices(); QVBoxLayout* vb = new QVBoxLayout(parent); for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it) { Config cfg(*it,Config::File); cfg.setGroup("Info"); QString type = cfg.readEntry("Type"); NetworkInterface* plugin = Network::loadPlugin(type); cfg.setGroup("Properties"); if ( plugin ) { QWidget* w; if ( (w=plugin->addStateWidget(parent,cfg)) ) { n++; vb->addWidget(w); } } } return n; } static QDict<NetworkInterface> *ifaces; /*! \internal */ NetworkInterface* Network::loadPlugin(const QString& type) { #ifndef QT_NO_COMPONENT if ( !ifaces ) ifaces = new QDict<NetworkInterface>; NetworkInterface *iface = ifaces->find(type); if ( !iface ) { +#ifdef Q_OS_MACX + QString libfile = QPEApplication::qpeDir() + "/plugins/network/lib" + type + ".dylib"; +#else QString libfile = QPEApplication::qpeDir() + "/plugins/network/lib" + type + ".so"; +#endif QLibrary lib(libfile); if ( !lib.queryInterface( IID_Network, (QUnknownInterface**)&iface ) == QS_OK ) return 0; ifaces->insert(type,iface); QStringList langs = Global::languageList(); for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) { QString lang = *it; QTranslator * trans = new QTranslator(qApp); QString tfn = QPEApplication::qpeDir()+"/i18n/"+lang+"/lib"+type+".qm"; if ( trans->load( tfn )) qApp->installTranslator( trans ); else delete trans; } } return iface; #else return 0; #endif } #include "network.moc" #endif // QT_NO_COP diff --git a/library/qlibrary_unix.cpp b/library/qlibrary_unix.cpp index 7740321..0229b7b 100644 --- a/library/qlibrary_unix.cpp +++ b/library/qlibrary_unix.cpp @@ -1,132 +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; } -#else // Q_OS_HPUX +#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; + DYLD_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(): %d", ret ); + } +#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 ); #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 ); 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/qpeapplication.cpp b/library/qpeapplication.cpp index d4734ae..a97efc0 100644 --- a/library/qpeapplication.cpp +++ b/library/qpeapplication.cpp @@ -1,540 +1,559 @@ /********************************************************************** ** 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. ** */ #define QTOPIA_INTERNAL_LANGLIST #include <stdlib.h> #include <unistd.h> +#ifndef Q_OS_MACX #include <linux/limits.h> // needed for some toolchains (PATH_MAX) +#endif #include <qfile.h> #include <qqueue.h> #ifdef Q_WS_QWS #ifndef QT_NO_COP #if QT_VERSION <= 231 #define private public #define sendLocally processEvent #include "qcopenvelope_qws.h" #undef private #else #include "qcopenvelope_qws.h" #endif #endif #include <qwindowsystem_qws.h> #endif #include <qtextstream.h> #include <qpalette.h> #include <qbuffer.h> #include <qptrdict.h> #include <qregexp.h> #include <qdir.h> #include <qlabel.h> #include <qdialog.h> #include <qdragobject.h> #include <qtextcodec.h> #include <qevent.h> #include <qtooltip.h> #include <qsignal.h> #include <qmainwindow.h> #include <qwidgetlist.h> #include <qpixmapcache.h> #if defined(Q_WS_QWS) && !defined(QT_NO_COP) #define QTOPIA_INTERNAL_INITAPP #include "qpeapplication.h" #include "qpestyle.h" #include "styleinterface.h" #if QT_VERSION >= 300 #include <qstylefactory.h> #else #include <qplatinumstyle.h> #include <qwindowsstyle.h> #include <qmotifstyle.h> #include <qmotifplusstyle.h> #include "lightstyle.h" #include <qpe/qlibrary.h> #endif #include "global.h" #include "resource.h" #if QT_VERSION <= 230 && defined(QT_NO_CODECS) #include "qutfcodec.h" #endif #include "config.h" #include "network.h" #ifdef QWS #include "fontmanager.h" #endif #include "alarmserver.h" #include "applnk.h" #include "qpemenubar.h" #include "textcodecinterface.h" #include "imagecodecinterface.h" #include <unistd.h> #include <sys/file.h> #include <sys/ioctl.h> +#ifndef QT_NO_SOUND #include <sys/soundcard.h> - +#endif #include "qt_override_p.h" class QPEApplicationData { public: QPEApplicationData ( ) : presstimer( 0 ), presswidget( 0 ), rightpressed( false ), kbgrabbed( false ), notbusysent( false ), preloaded( false ), forceshow( false ), nomaximize( false ), keep_running( true ), qcopQok( false ), qpe_main_widget( 0 ) {} int presstimer; QWidget* presswidget; QPoint presspos; bool rightpressed : 1; bool kbgrabbed : 1; bool notbusysent : 1; bool preloaded : 1; bool forceshow : 1; bool nomaximize : 1; bool keep_running : 1; bool qcopQok : 1; QStringList langs; QString appName; struct QCopRec { QCopRec( const QCString &ch, const QCString &msg, const QByteArray &d ) : channel( ch ), message( msg ), data( d ) { } QCString channel; QCString message; QByteArray data; }; QWidget* qpe_main_widget; QGuardedPtr<QWidget> lastraised; QQueue<QCopRec> qcopq; QString styleName; QString decorationName; void enqueueQCop( const QCString &ch, const QCString &msg, const QByteArray &data ) { qcopq.enqueue( new QCopRec( ch, msg, data ) ); } void sendQCopQ() { if (!qcopQok ) return; QCopRec * r; while((r=qcopq.dequeue())) { // remove from queue before sending... // event loop can come around again before getting // back from sendLocally #ifndef QT_NO_COP QCopChannel::sendLocally( r->channel, r->message, r->data ); #endif delete r; } } static void show_mx(QWidget* mw, bool nomaximize, const QString & = QString::null ) { // ugly hack, remove that later after finding a sane solution // Addendum: Only Sharp currently has models with high resolution but (physically) small displays, // so this is only useful if QT_QWS_SIMPAD is NOT defined. E.g. SIMpad has 800x600 but has // a (physically) large enough display to use the small icons #if defined(OPIE_HIGH_RES_SMALL_PHY) if ( QPEApplication::desktop() ->width() >= 600 && ( mw->inherits("QMainWindow") || mw->isA("QMainWindow") ) ) { ( ( QMainWindow* ) mw )->setUsesBigPixmaps( true ); } #endif if ( mw->layout() && mw->inherits("QDialog") ) { QPEApplication::showDialog((QDialog*)mw, nomaximize); } else { #ifdef Q_WS_QWS if ( !nomaximize ) mw->showMaximized(); else #endif mw->show(); } } static bool setWidgetCaptionFromAppName( QWidget* /*mw*/, const QString& /*appName*/, const QString& /*appsPath*/ ) { /* // This works but disable it for now until it is safe to apply // What is does is scan the .desktop files of all the apps for // the applnk that has the corresponding argv[0] as this program // then it uses the name stored in the .desktop file as the caption // for the main widget. This saves duplicating translations for // the app name in the program and in the .desktop files. AppLnkSet apps( appsPath ); QList<AppLnk> appsList = apps.children(); for ( QListIterator<AppLnk> it(appsList); it.current(); ++it ) { if ( (*it)->exec() == appName ) { mw->setCaption( (*it)->name() ); return TRUE; } } */ return FALSE; } void show(QWidget* mw, bool nomax) { setWidgetCaptionFromAppName( mw, appName, QPEApplication::qpeDir() + "apps" ); nomaximize = nomax; qpe_main_widget = mw; qcopQok = TRUE; #ifndef QT_NO_COP sendQCopQ(); #endif if ( preloaded ) { if (forceshow) show_mx(mw, nomax); } else if ( keep_running ) { show_mx(mw, nomax); } } void loadTextCodecs() { QString path = QPEApplication::qpeDir() + "/plugins/textcodecs"; +#ifdef Q_OS_MACX + QDir dir( path, "lib*.dylib" ); +#else QDir dir( path, "lib*.so" ); +#endif QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { TextCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaTextCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QValueList<int> mibs = iface->mibEnums(); for (QValueList<int>::ConstIterator i = mibs.begin(); i != mibs.end(); ++i) { (void)iface->createForMib(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } void loadImageCodecs() { QString path = QPEApplication::qpeDir() + "/plugins/imagecodecs"; +#ifdef Q_OS_MACX + QDir dir( path, "lib*.dylib" ); +#else QDir dir( path, "lib*.so" ); +#endif QStringList list; if ( dir. exists ( )) list = dir.entryList(); QStringList::Iterator it; for ( it = list.begin(); it != list.end(); ++it ) { ImageCodecInterface *iface = 0; QLibrary *lib = new QLibrary( path + "/" + *it ); if ( lib->queryInterface( IID_QtopiaImageCodec, (QUnknownInterface**)&iface ) == QS_OK && iface ) { QStringList formats = iface->keys(); for (QStringList::ConstIterator i = formats.begin(); i != formats.end(); ++i) { (void)iface->installIOHandler(*i); // ### it exists now; need to remember if we can delete it } } else { lib->unload(); delete lib; } } } }; class ResourceMimeFactory : public QMimeSourceFactory { public: ResourceMimeFactory() : resImage( 0 ) { setFilePath( Global::helpPath() ); setExtensionType( "html", "text/html;charset=UTF-8" ); } ~ResourceMimeFactory() { delete resImage; } const QMimeSource* data( const QString& abs_name ) const { const QMimeSource * r = QMimeSourceFactory::data( abs_name ); if ( !r ) { int sl = abs_name.length(); do { sl = abs_name.findRev( '/', sl - 1 ); QString name = sl >= 0 ? abs_name.mid( sl + 1 ) : abs_name; int dot = name.findRev( '.' ); if ( dot >= 0 ) name = name.left( dot ); QImage img = Resource::loadImage( name ); if ( !img.isNull() ) { delete resImage; resImage = new QImageDrag( img ); r = resImage; } } while ( !r && sl > 0 ); } return r; } private: mutable QImageDrag *resImage; }; static int& hack(int& i) { #if QT_VERSION <= 230 && defined(QT_NO_CODECS) // These should be created, but aren't in Qt 2.3.0 (void)new QUtf8Codec; (void)new QUtf16Codec; #endif return i; } static int muted = 0; static int micMuted = 0; static void setVolume( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "VolumePercent", 50 ); +#ifndef QT_NO_SOUND int fd = 0; if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { int vol = muted ? 0 : percent; // set both channels to same volume vol |= vol << 8; ioctl( fd, MIXER_WRITE( 0 ), &vol ); ::close( fd ); } +#endif } break; } } static void setMic( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "Mic", 50 ); +#ifndef QT_NO_SOUND int fd = 0; int mic = micMuted ? 0 : percent; if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { ioctl( fd, MIXER_WRITE( SOUND_MIXER_MIC ), &mic ); ::close( fd ); } +#endif } break; } } static void setBass( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "BassPercent", 50 ); +#ifndef QT_NO_SOUND int fd = 0; int bass = percent; if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { ioctl( fd, MIXER_WRITE( SOUND_MIXER_BASS ), &bass ); ::close( fd ); } +#endif } break; } } static void setTreble( int t = 0, int percent = -1 ) { switch ( t ) { case 0: { Config cfg( "qpe" ); cfg.setGroup( "Volume" ); if ( percent < 0 ) percent = cfg.readNumEntry( "TreblePercent", 50 ); +#ifndef QT_NO_SOUND int fd = 0; int treble = percent; if ( ( fd = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { ioctl( fd, MIXER_WRITE( SOUND_MIXER_TREBLE ), &treble ); ::close( fd ); } +#endif } break; } } /*! \class QPEApplication qpeapplication.h \brief The QPEApplication class implements various system services that are available to all Qtopia applications. Simply by using QPEApplication instead of QApplication, a standard Qt application becomes a Qtopia application. It automatically follows style changes, quits and raises, and in the case of \link docwidget.html document-oriented\endlink applications, changes the currently displayed document in response to the environment. To create a \link docwidget.html document-oriented\endlink application use showMainDocumentWidget(); to create a non-document-oriented application use showMainWidget(). The keepRunning() function indicates whether the application will continue running after it's processed the last \link qcop.html QCop\endlink message. This can be changed using setKeepRunning(). A variety of signals are emitted when certain events occur, for example, timeChanged(), clockChanged(), weekChanged(), dateFormatChanged() and volumeChanged(). If the application receives a \link qcop.html QCop\endlink message on the application's QPE/Application/\e{appname} channel, the appMessage() signal is emitted. There are also flush() and reload() signals, which are emitted when synching begins and ends respectively - upon these signals, the application should save and reload any data files that are involved in synching. Most of these signals will initially be received and unfiltered through the appMessage() signal. This class also provides a set of useful static functions. The qpeDir() and documentDir() functions return the respective paths. The grabKeyboard() and ungrabKeyboard() functions are used to control whether the application takes control of the device's physical buttons (e.g. application launch keys). The stylus' mode of operation is set with setStylusOperation() and retrieved with stylusOperation(). There are also setInputMethodHint() and inputMethodHint() functions. \ingroup qtopiaemb */ /*! \fn void QPEApplication::clientMoused() \internal */ /*! \fn void QPEApplication::timeChanged(); This signal is emitted when the time changes outside the normal passage of time, i.e. if the time is set backwards or forwards. */ /*! \fn void QPEApplication::clockChanged( bool ampm ); This signal is emitted when the user changes the clock's style. If \a ampm is TRUE, the user wants a 12-hour AM/PM clock, otherwise, they want a 24-hour clock. */ /*! \fn void QPEApplication::volumeChanged( bool muted ) This signal is emitted whenever the mute state is changed. If \a muted is TRUE, then sound output has been muted. */ /*! \fn void QPEApplication::weekChanged( bool startOnMonday ) This signal is emitted if the week start day is changed. If \a startOnMonday is TRUE then the first day of the week is Monday; if \a startOnMonday is FALSE then the first day of the week is Sunday. */ /*! \fn void QPEApplication::dateFormatChanged(DateFormat) This signal is emitted whenever the date format is changed. */ /*! \fn void QPEApplication::flush() ### */ /*! \fn void QPEApplication::reload() */ void QPEApplication::processQCopFile() { QString qcopfn("/tmp/qcop-msg-"); qcopfn += d->appName; // append command name QFile f(qcopfn); if ( f.open(IO_ReadWrite) ) { #ifndef Q_OS_WIN32 flock(f.handle(), LOCK_EX); #endif QDataStream ds(&f); QCString channel, message; QByteArray data; while(!ds.atEnd()) { ds >> channel >> message >> data; d->enqueueQCop(channel,message,data); } ::ftruncate(f.handle(), 0); #ifndef Q_OS_WIN32 f.flush(); flock(f.handle(), LOCK_UN); #endif } #endif } @@ -1524,261 +1543,267 @@ void QPEApplication::pidMessage( const QCString& msg, const QByteArray& data) }else { bool p = d->keep_running; d->keep_running = FALSE; emit appMessage( msg, data); if ( d->keep_running ) { d->notbusysent = FALSE; raiseAppropriateWindow(); if ( !p ) { // Tell the system we're still chugging along... #ifndef QT_NO_COP QCopEnvelope e("QPE/System", "appRaised(QString)"); e << d->appName; #endif } } if ( p ) d->keep_running = p; } #endif } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. \sa showMainDocumentWidget() */ void QPEApplication::showMainWidget( QWidget* mw, bool nomaximize ) { d->show(mw, nomaximize ); } /*! Sets widget \a mw as the mainWidget() and shows it. For small windows, consider passing TRUE for \a nomaximize rather than the default FALSE. This calls designates the application as a \link docwidget.html document-oriented\endlink application. The \a mw widget \e must have this slot: setDocument(const QString&). \sa showMainWidget() */ void QPEApplication::showMainDocumentWidget( QWidget* mw, bool nomaximize ) { if ( mw && argc() == 2 ) Global::setDocument( mw, QString::fromUtf8(argv()[1]) ); d->show(mw, nomaximize ); } /*! If an application is started via a \link qcop.html QCop\endlink message, the application will process the \link qcop.html QCop\endlink message and then quit. If the application calls this function while processing a \link qcop.html QCop\endlink message, after processing its outstanding \link qcop.html QCop\endlink messages the application will start 'properly' and show itself. \sa keepRunning() */ void QPEApplication::setKeepRunning() { if ( qApp && qApp->inherits( "QPEApplication" ) ) { QPEApplication * qpeApp = ( QPEApplication* ) qApp; qpeApp->d->keep_running = TRUE; } } /*! Returns TRUE if the application will quit after processing the current list of qcop messages; otherwise returns FALSE. \sa setKeepRunning() */ bool QPEApplication::keepRunning() const { return d->keep_running; } /*! \internal */ void QPEApplication::internalSetStyle( const QString &style ) { #if QT_VERSION >= 300 if ( style == "QPE" ) { setStyle( new QPEStyle ); } else { QStyle *s = QStyleFactory::create( style ); if ( s ) setStyle( s ); } #else if ( style == "Windows" ) { setStyle( new QWindowsStyle ); } else if ( style == "QPE" ) { setStyle( new QPEStyle ); } else if ( style == "Light" ) { setStyle( new LightStyle ); } #ifndef QT_NO_STYLE_PLATINUM else if ( style == "Platinum" ) { setStyle( new QPlatinumStyle ); } #endif #ifndef QT_NO_STYLE_MOTIF else if ( style == "Motif" ) { setStyle( new QMotifStyle ); } #endif #ifndef QT_NO_STYLE_MOTIFPLUS else if ( style == "MotifPlus" ) { setStyle( new QMotifPlusStyle ); } #endif else { QStyle *sty = 0; QString path = QPEApplication::qpeDir ( ) + "/plugins/styles/"; +#ifdef Q_OS_MACX + if ( style. find ( ".dylib" ) > 0 ) + path += style; + else + path = path + "lib" + style. lower ( ) + ".dylib"; // compatibility +#else if ( style. find ( ".so" ) > 0 ) path += style; else path = path + "lib" + style. lower ( ) + ".so"; // compatibility - +#endif static QLibrary *lastlib = 0; static StyleInterface *lastiface = 0; QLibrary *lib = new QLibrary ( path ); StyleInterface *iface = 0; if (( lib-> queryInterface ( IID_Style, ( QUnknownInterface ** ) &iface ) == QS_OK ) && iface ) sty = iface-> style ( ); if ( sty ) { setStyle ( sty ); if ( lastiface ) lastiface-> release ( ); lastiface = iface; if ( lastlib ) { lastlib-> unload ( ); delete lastlib; } lastlib = lib; } else { if ( iface ) iface-> release ( ); delete lib; setStyle ( new LightStyle ( )); } } #endif } /*! \internal */ void QPEApplication::prepareForTermination( bool willrestart ) { if ( willrestart ) { // Draw a big wait icon, the image can be altered in later revisions // QWidget *d = QApplication::desktop(); QImage img = Resource::loadImage( "launcher/new_wait" ); QPixmap pix; pix.convertFromImage( img.smoothScale( 1 * img.width(), 1 * img.height() ) ); QLabel *lblWait = new QLabel( 0, "wait hack!", QWidget::WStyle_Customize | QWidget::WStyle_NoBorder | QWidget::WStyle_Tool ); lblWait->setPixmap( pix ); lblWait->setAlignment( QWidget::AlignCenter ); lblWait->show(); lblWait->showMaximized(); } #ifndef SINGLE_APP { QCopEnvelope envelope( "QPE/System", "forceQuit()" ); } processEvents(); // ensure the message goes out. sleep( 1 ); // You have 1 second to comply. #endif } /*! \internal */ void QPEApplication::shutdown() { // Implement in server's QPEApplication subclass } /*! \internal */ void QPEApplication::restart() { // Implement in server's QPEApplication subclass } static QPtrDict<void>* stylusDict = 0; static void createDict() { if ( !stylusDict ) stylusDict = new QPtrDict<void>; } /*! Returns the current StylusMode for widget \a w. \sa setStylusOperation() StylusMode */ QPEApplication::StylusMode QPEApplication::stylusOperation( QWidget* w ) { if ( stylusDict ) return ( StylusMode ) ( int ) stylusDict->find( w ); return LeftOnly; } /*! \enum QPEApplication::StylusMode \value LeftOnly the stylus only generates LeftButton events (the default). \value RightOnHold the stylus generates RightButton events if the user uses the press-and-hold gesture. \sa setStylusOperation() stylusOperation() */ /*! Causes widget \a w to receive mouse events according to the stylus \a mode. \sa stylusOperation() StylusMode */ void QPEApplication::setStylusOperation( QWidget * w, StylusMode mode ) { createDict(); if ( mode == LeftOnly ) { stylusDict->remove ( w ); w->removeEventFilter( qApp ); } else { stylusDict->insert( w, ( void* ) mode ); connect( w, SIGNAL( destroyed() ), qApp, SLOT( removeSenderFromStylusDict() ) ); w->installEventFilter( qApp ); } } /*! diff --git a/library/qpedecoration_qws.cpp b/library/qpedecoration_qws.cpp index 933542d..bac1a75 100644 --- a/library/qpedecoration_qws.cpp +++ b/library/qpedecoration_qws.cpp @@ -387,261 +387,269 @@ void WindowDecorationInterface::drawArea( Area a, QPainter *p, const WindowData break; case Title: { const QColorGroup &cg = wd->palette.active(); QBrush titleBrush; QPen titleLines; if ( wd->flags & WindowData::Active ) { titleBrush = cg.brush(QColorGroup::Highlight); titleLines = titleBrush.color().dark(); } else { titleBrush = cg.brush(QColorGroup::Background); titleLines = titleBrush.color(); } p->fillRect( r.x(), r.y()-th, r.width(), th, titleBrush); p->setPen( titleLines ); for ( int i = r.y()-th; i < r.y(); i += 2 ) p->drawLine( r.left(), i, r.right(), i ); } break; case TitleText: p->drawText( r.x()+3+metric(HelpWidth,wd), r.top()-th, r.width()-metric(OKWidth,wd)-metric(CloseWidth,wd), th, QPainter::AlignVCenter, wd->caption); break; } } void WindowDecorationInterface::drawButton( Button b, QPainter *p, const WindowData *wd, int x, int y, int, int, QWSButton::State state ) const { QImage *img = 0; switch ( b ) { case OK: img = okImage(metric(TitleHeight,wd)); break; case Close: img = closeImage(metric(TitleHeight,wd)); break; case Help: img = helpImage(metric(TitleHeight,wd)); break; case Maximize: img = maximizeImage(metric(TitleHeight,wd)); break; } if ( img ) { if ((state & QWSButton::MouseOver) && (state & QWSButton::Clicked)) p->drawImage(x+2, y+2, *img); else p->drawImage(x+1, y+1, *img); } } QRegion WindowDecorationInterface::mask( const WindowData *wd ) const { int th = metric(TitleHeight,wd); QRect rect( wd->rect ); QRect r(rect.left() - metric(LeftBorder,wd), rect.top() - th - metric(TopBorder,wd), rect.width() + metric(LeftBorder,wd) + metric(RightBorder,wd), rect.height() + th + metric(TopBorder,wd) + metric(BottomBorder,wd)); return QRegion(r) - rect; } class DefaultWindowDecoration : public WindowDecorationInterface { public: DefaultWindowDecoration() : ref(0) {} QString name() const { return "Default"; } QPixmap icon() const { return QPixmap(); } QRESULT queryInterface( const QUuid &uuid, QUnknownInterface **iface ) { *iface = 0; if ( uuid == IID_QUnknown ) *iface = this; else if ( uuid == IID_WindowDecoration ) *iface = this; if ( *iface ) (*iface)->addRef(); return QS_OK; } Q_REFCOUNT private: ulong ref; }; static WindowDecorationInterface *wdiface = 0; static QLibrary *wdlib = 0; static QString libname; //=========================================================================== QPEDecoration::QPEDecoration() : QWSDefaultDecoration() { init ( libname ); } QPEDecoration::QPEDecoration( const QString &plugin ) : QWSDefaultDecoration() { init ( plugin ); } void QPEDecoration::init ( const QString &plugin ) { libname = plugin; if ( wdlib ) { wdiface->release(); wdlib->unload(); delete wdlib; wdlib = 0; } else { delete wdiface; } WindowDecorationInterface *iface = 0; QString path = QPEApplication::qpeDir() + "/plugins/decorations/"; +#ifdef Q_OS_MACX + if ( plugin.find( ".dylib" ) > 0 ) { +#else if ( plugin.find( ".so" ) > 0 ) { +#endif // full library name supplied path += plugin; } else { +#ifdef Q_OS_MACX + path += "lib" + plugin.lower() + ".dylib"; // compatibility +#else path += "lib" + plugin.lower() + ".so"; // compatibility +#endif } QLibrary *lib = new QLibrary( path ); if ( lib->queryInterface( IID_WindowDecoration, (QUnknownInterface**)&iface ) == QS_OK && iface ) { wdiface = iface; wdlib = lib; } else { delete lib; wdiface = new DefaultWindowDecoration; } helpFile = QString(qApp->argv()[0]) + ".html"; QStringList helpPath = Global::helpPath(); helpExists = FALSE; for (QStringList::ConstIterator it=helpPath.begin(); it!=helpPath.end() && !helpExists; ++it) { helpExists = QFile::exists( *it + "/" + helpFile ); //qDebug ( "Checking %s/%s for help: %d", (*it).latin1(), helpFile.latin1(),helpExists); } qpeManager = new QPEManager( this ); // Qtopia 1.5 compatibility imageOk = *okImage ( 15 ); imageClose = *closeImage ( 15 ); imageHelp = *helpImage ( 15 ); } QPEDecoration::~QPEDecoration() { delete qpeManager; } const char **QPEDecoration::menuPixmap() { return (const char **)0; } const char **QPEDecoration::closePixmap() { return (const char **)qpe_close_xpm; } const char **QPEDecoration::minimizePixmap() { return (const char **)qpe_accept_xpm; } const char **QPEDecoration::maximizePixmap() { return (const char **)0; } const char **QPEDecoration::normalizePixmap() { return (const char **)0; } int QPEDecoration::getTitleHeight( const QWidget *w ) { WindowDecorationInterface::WindowData wd; windowData( w, wd ); return wdiface->metric(WindowDecorationInterface::TitleHeight,&wd); } /* If rect is empty, no frame is added. (a hack, really) */ QRegion QPEDecoration::region(const QWidget *widget, const QRect &rect, QWSDecoration::Region type) { qpeManager->updateActive(); WindowDecorationInterface::WindowData wd; windowData( widget, wd ); wd.rect = rect; int titleHeight = wdiface->metric(WindowDecorationInterface::TitleHeight,&wd); int okWidth = wdiface->metric(WindowDecorationInterface::OKWidth,&wd); int closeWidth = wdiface->metric(WindowDecorationInterface::CloseWidth,&wd); int helpWidth = wdiface->metric(WindowDecorationInterface::HelpWidth,&wd); int grab = wdiface->metric(WindowDecorationInterface::CornerGrabSize,&wd); QRegion region; switch ((int)type) { case Menu: break; case Maximize: if ( !widget->inherits( "QDialog" ) && qApp->desktop()->width() > 350 ) { int maximizeWidth = wdiface->metric(WindowDecorationInterface::MaximizeWidth,&wd); int left = rect.right() - maximizeWidth - closeWidth; if ( ((HackWidget *)widget)->needsOk() ) left -= okWidth; QRect r(left, rect.top() - titleHeight, closeWidth, titleHeight); region = r; } break; case Minimize: if ( ((HackWidget *)widget)->needsOk() ) { QRect r(rect.right() - okWidth, rect.top() - titleHeight, okWidth, titleHeight); if (r.left() > rect.left() + titleHeight) region = r; } break; case Close: { int left = rect.right() - closeWidth; if ( ((HackWidget *)widget)->needsOk() ) left -= okWidth; QRect r(left, rect.top() - titleHeight, closeWidth, titleHeight); region = r; } break; case Title: if ( !widget->isMaximized() ) { int width = rect.width() - helpWidth - closeWidth; if ( ((HackWidget *)widget)->needsOk() ) width -= okWidth; QRect r(rect.left()+helpWidth, rect.top() - titleHeight, width, titleHeight); if (r.width() > 0) region = r; } break; case Help: if ( helpExists || widget->testWFlags(Qt::WStyle_ContextHelp) ) { QRect r(rect.left(), rect.top() - titleHeight, helpWidth, titleHeight); region = r; diff --git a/library/sound.cpp b/library/sound.cpp index c8704f9..5b67995 100644 --- a/library/sound.cpp +++ b/library/sound.cpp @@ -1,159 +1,162 @@ /********************************************************************** ** 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. ** **********************************************************************/ #include <qpe/resource.h> #include <qpe/sound.h> #include <qpe/qcopenvelope_qws.h> #include <qsound.h> #include <qfile.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> + +#ifndef QT_NO_SOUND #include <sys/soundcard.h> +#endif #include "config.h" #include <qmessagebox.h> #ifndef QT_NO_SOUND static int WAVsoundDuration(const QString& filename) { // bad solution // most of this is copied from qsoundqss.cpp QFile input(filename); if ( !input.open(IO_ReadOnly) ) return 0; struct QRiffChunk { char id[4]; Q_UINT32 size; char data[4/*size*/]; } chunk; struct { Q_INT16 formatTag; Q_INT16 channels; Q_INT32 samplesPerSec; Q_INT32 avgBytesPerSec; Q_INT16 blockAlign; Q_INT16 wBitsPerSample; } chunkdata; int total = 0; while(1) { // Keep reading chunks... const int n = sizeof(chunk)-sizeof(chunk.data); if ( input.readBlock((char*)&chunk,n) != n ) break; if ( qstrncmp(chunk.id,"data",4) == 0 ) { total += chunkdata.avgBytesPerSec ? chunk.size * 1000 / chunkdata.avgBytesPerSec : 0; //qDebug("%d bytes of PCM (%dms)", chunk.size,chunkdata.avgBytesPerSec ? chunk.size * 1000 / chunkdata.avgBytesPerSec : 0); input.at(input.at()+chunk.size-4); } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { char d[4]; if ( input.readBlock(d,4) != 4 ) return 0; if ( qstrncmp(d,"WAVE",4) != 0 ) { // skip //qDebug("skip %.4s RIFF chunk",d); if ( chunk.size < 10000000 ) (void)input.at(input.at()+chunk.size-4); } } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { if ( input.readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) return 0; #define WAVE_FORMAT_PCM 1 if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); return 0; } } else { //qDebug("skip %.4s chunk",chunk.id); // ignored chunk if ( chunk.size < 10000000 ) (void)input.at(input.at()+chunk.size); } } //qDebug("%dms",total); return total; } class SoundData : public QSound { public: SoundData ( const QString& name ) : QSound ( Resource::findSound ( name )), filename ( Resource::findSound ( name )) { loopsleft=0; ms = WAVsoundDuration(filename); } void playLoop ( int loopcnt = -1 ) { // needs server support loopsleft = loopcnt; if ( ms ) startTimer ( ms > 50 ? ms-50 : 0 ); // 50 for latency play ( ); } void timerEvent ( QTimerEvent *e ) { if ( loopsleft >= 0 ) { if ( --loopsleft <= 0 ) { killTimer ( e-> timerId ( )); loopsleft = 0; return; } } play(); } bool isFinished ( ) const { return ( loopsleft == 0 ); } private: QString filename; int loopsleft; int ms; }; #endif /*! Opens a wave sound file \a name for playing * Resource is used for finding the file **/ Sound::Sound(const QString& name) { #ifndef QT_NO_SOUND d = new SoundData(name); #endif } /*! Destroys the sound */ Sound::~Sound() diff --git a/library/storage.cpp b/library/storage.cpp index dc5cc22..f8b75d0 100644 --- a/library/storage.cpp +++ b/library/storage.cpp @@ -1,344 +1,376 @@ /********************************************************************** ** Copyright (C) Holger 'zecke' Freyther <freyther@kde.org> ** Copyright (C) Lorn Potter <llornkcor@handhelds.org> ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Opie 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 <qpe/storage.h> #include <qpe/custom.h> #include <qfile.h> #include <qtimer.h> #include <qcopchannel_qws.h> #include <stdio.h> #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) #include <sys/vfs.h> #include <mntent.h> #endif +#ifdef Q_OS_MACX +# include <sys/param.h> +# include <sys/ucred.h> +# include <sys/mount.h> +# include <stdio.h> // For strerror() +# include <errno.h> +#endif /* Q_OS_MACX */ + #include <qstringlist.h> -#include <sys/vfs.h> -#include <mntent.h> +// Shouldn't be here ! (eilers) +// #include <sys/vfs.h> +// #include <mntent.h> static bool isCF(const QString& m) { + +#ifndef Q_OS_MACX FILE* f = fopen("/var/run/stab", "r"); if (!f) f = fopen("/var/state/pcmcia/stab", "r"); if (!f) f = fopen("/var/lib/pcmcia/stab", "r"); if ( f ) { char line[1024]; char devtype[80]; char devname[80]; while ( fgets( line, 1024, f ) ) { // 0 ide ide-cs 0 hda 3 0 if ( sscanf(line,"%*d %s %*s %*s %s", devtype, devname )==2 ) { if ( QString(devtype) == "ide" && m.find(devname)>0 ) { fclose(f); return TRUE; } } } fclose(f); } +#endif /* Q_OS_MACX */ return FALSE; } /*! \class StorageInfo storage.h \brief The StorageInfo class describes the disks mounted on the file system. This class provides access to the mount information for the Linux filesystem. Each mount point is represented by the FileSystem class. To ensure this class has the most up to date size information, call the update() method. Note that this will automatically be signaled by the operating system when a disk has been mounted or unmounted. \ingroup qtopiaemb */ /*! Constructor that determines the current mount points of the filesystem. The standard \a parent parameters is passed on to QObject. */ StorageInfo::StorageInfo( QObject *parent ) : QObject( parent ) { mFileSystems.setAutoDelete( TRUE ); channel = new QCopChannel( "QPE/Card", this ); connect( channel, SIGNAL(received(const QCString &, const QByteArray &)), this, SLOT(cardMessage( const QCString &, const QByteArray &)) ); update(); } /*! Returns the longest matching FileSystem that starts with the same prefix as \a filename as its mount point. */ const FileSystem *StorageInfo::fileSystemOf( const QString &filename ) { for (QListIterator<FileSystem> i(mFileSystems); i.current(); ++i) { if ( filename.startsWith( (*i)->path() ) ) return (*i); } return 0; } void StorageInfo::cardMessage( const QCString& msg, const QByteArray& ) { if ( msg == "mtabChanged()" ) update(); } /*! Updates the mount and free space available information for each mount point. This method is automatically called when a disk is mounted or unmounted. */ // cause of the lack of a d pointer we need // to store informations in a config file :( void StorageInfo::update() { //qDebug("StorageInfo::updating"); #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) struct mntent *me; FILE *mntfp = setmntent( "/etc/mtab", "r" ); QStringList curdisks; QStringList curopts; QStringList curfs; bool rebuild = FALSE; int n=0; if ( mntfp ) { while ( (me = getmntent( mntfp )) != 0 ) { QString fs = me->mnt_fsname; if ( fs.left(7)=="/dev/hd" || fs.left(7)=="/dev/sd" || fs.left(8)=="/dev/mtd" || fs.left(9) == "/dev/mmcd" || fs.left( 14 ) == "/dev/mmc/part1" || fs.left(5)=="tmpfs" || fs.left(9)=="/dev/root" ) { n++; curdisks.append(fs); curopts.append( me->mnt_opts ); //qDebug("-->fs %s opts %s", fs.latin1(), me->mnt_opts ); curfs.append( me->mnt_dir ); bool found = FALSE; for (QListIterator<FileSystem> i(mFileSystems); i.current(); ++i) { if ( (*i)->disk() == fs ) { found = TRUE; break; } } if ( !found ) rebuild = TRUE; } } endmntent( mntfp ); } if ( rebuild || n != (int)mFileSystems.count() ) { mFileSystems.clear(); QStringList::ConstIterator it=curdisks.begin(); QStringList::ConstIterator fsit=curfs.begin(); QStringList::ConstIterator optsIt=curopts.begin(); for (; it!=curdisks.end(); ++it, ++fsit, ++optsIt) { QString opts = *optsIt; QString disk = *it; QString humanname; bool removable = FALSE; if ( isCF(disk) ) { humanname = tr("CF Card"); removable = TRUE; } else if ( disk == "/dev/hda1" ) { humanname = tr("Hard Disk"); } else if ( disk.left(9) == "/dev/mmcd" ) { humanname = tr("SD Card"); removable = TRUE; } else if ( disk.left( 14 ) == "/dev/mmc/part1" ) { humanname = tr("MMC Card"); removable = TRUE; } else if ( disk.left(7) == "/dev/hd" ) humanname = tr("Hard Disk") + " " + disk; else if ( disk.left(7) == "/dev/sd" ) humanname = tr("SCSI Hard Disk") + " " + disk; else if ( disk.left(14) == "/dev/mtdblock6" ) //openzaurus ramfs humanname = tr("Internal Memory"); else if ( disk == "/dev/mtdblock1" || humanname == "/dev/mtdblock/1" ) humanname = tr("Internal Storage"); else if ( disk.left(14) == "/dev/mtdblock/" ) humanname = tr("Internal Storage") + " " + disk; else if ( disk.left(13) == "/dev/mtdblock" ) humanname = tr("Internal Storage") + " " + disk; else if ( disk.left(9) == "/dev/root" ) humanname = tr("Internal Storage") + " " + disk; else if ( disk.left(5) == "tmpfs" ) //ipaqs /mnt/ramfs humanname = tr("Internal Memory"); FileSystem *fs = new FileSystem( disk, *fsit, humanname, removable, opts ); mFileSystems.append( fs ); } emit disksChanged(); } else { // just update them for (QListIterator<FileSystem> i(mFileSystems); i.current(); ++i) i.current()->update(); } #endif } bool deviceTab( const char *device) { QString name = device; bool hasDevice=false; + +#ifdef Q_OS_MACX + // Darwin (MacOS X) + struct statfs** mntbufp; + int count = 0; + if ( ( count = getmntinfo( mntbufp, MNT_WAIT ) ) == 0 ){ + qWarning("deviceTab: Error in getmntinfo(): %s",strerror( errno ) ); + hasDevice = false; + } + for( int i = 0; i < count; i++ ){ + QString deviceName = mntbufp[i]->f_mntfromname; + qDebug(deviceName); + if( deviceName.left( name.length() ) == name ) + hasDevice = true; + } +#else + // Linux struct mntent *me; FILE *mntfp = setmntent( "/etc/mtab", "r" ); if ( mntfp ) { while ( (me = getmntent( mntfp )) != 0 ) { QString deviceName = me->mnt_fsname; // qDebug(deviceName); if( deviceName.left(name.length()) == name) { hasDevice = true; } } } endmntent( mntfp ); +#endif /* Q_OS_MACX */ + + return hasDevice; } /*! * @fn static bool StorageInfo::hasCf() * @brief returns whether device has Cf mounted * */ bool StorageInfo::hasCf() { return deviceTab("/dev/hd"); } /*! * @fn static bool StorageInfo::hasSd() * @brief returns whether device has SD mounted * */ bool StorageInfo::hasSd() { return deviceTab("/dev/mmcd"); } /*! * @fn static bool StorageInfo::hasMmc() * @brief reutrns whether device has mmc mounted * */ bool StorageInfo::hasMmc() { bool hasMmc=false; if( deviceTab("/dev/mmc/part")) hasMmc=true; if( deviceTab("/dev/mmcd")) hasMmc=true; return hasMmc; } /*! \fn const QList<FileSystem> &StorageInfo::fileSystems() const Returns a list of all available mounted file systems. \warning This may change in Qtopia 3.x to return only relevant Qtopia file systems (and ignore mount points such as /tmp) */ /*! \fn void StorageInfo::disksChanged() Gets emitted when a disk has been mounted or unmounted, such as when a CF c */ //--------------------------------------------------------------------------- FileSystem::FileSystem( const QString &disk, const QString &path, const QString &name, bool rem, const QString &o ) : fsdisk( disk ), fspath( path ), humanname( name ), blkSize(512), totalBlks(0), availBlks(0), removable( rem ), opts( o ) { update(); } void FileSystem::update() { #if defined(_OS_LINUX_) || defined(Q_OS_LINUX) struct statfs fs; if ( !statfs( fspath.latin1(), &fs ) ) { blkSize = fs.f_bsize; totalBlks = fs.f_blocks; availBlks = fs.f_bavail; } else { blkSize = 0; totalBlks = 0; availBlks = 0; } #endif } /*! \class FileSystem storage.h \brief The FileSystem class describes a single mount point. This class simply returns information about a mount point, including file system name, mount point, human readable name, size information and mount options information. \ingroup qtopiaemb \sa StorageInfo */ /*! \fn const QString &FileSystem::disk() const Returns the file system name, such as /dev/hda3 */ /*! \fn const QString &FileSystem::path() const Returns the mount path, such as /home */ /*! \fn const QString &FileSystem::name() const Returns the translated, human readable name for the mount directory. */ /*! \fn const QString &FileSystem::options() const Returns the mount options */ /*! \fn long FileSystem::blockSize() const Returns the size of each block on the file system. */ /*! \fn long FileSystem::totalBlocks() const Returns the total number of blocks on the file system */ /*! \fn long FileSystem::availBlocks() const Returns the number of available blocks on the file system */ /*! \fn bool FileSystem::isRemovable() const Returns flag whether the file system can be removed, such as a CF card would be removable, but the internal memory wouldn't */ /*! \fn bool FileSystem::isWritable() const Returns flag whether the file system is mounted as writable or read-only. Returns FALSE if read-only, TRUE if read and write. */ /*! \fn QStringList StorageInfo::fileSystemNames() const Returns a list of filesystem names. */ |