/* CR3 for OpenInkpot (XCB) */ #include <stdint.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <crengine.h> #include <crgui.h> #include <crtrace.h> #include <crtest.h> #include "cr3main.h" #include "mainwnd.h" #include <locale.h> #include <libintl.h> #include <cri18n.h> #include <QtGui/QApplication> #include <QtGui/QMainWindow> #include <QtGui/QPainter> #include <QtGui/QResizeEvent> #include <QEvent> #include <QtGui/QKeyEvent> // Qt code =================================================================== static V3DocViewWin * main_win = NULL; class CRQtScreen; class CRQtWindowManager; class MainWindow : public QMainWindow { //Q_OBJECT CRQtWindowManager * _wm; public: MainWindow(CRQtWindowManager * wm) : _wm(wm) { } ~MainWindow() { } protected: virtual void paintEvent ( QPaintEvent * event ); virtual void keyPressEvent ( QKeyEvent * event ); virtual void resizeEvent ( QResizeEvent * event ); virtual void wheelEvent ( QWheelEvent * event ); virtual void mouseMoveEvent ( QMouseEvent * event ); virtual void mousePressEvent ( QMouseEvent * event ); virtual void mouseReleaseEvent ( QMouseEvent * event ); virtual void customEvent ( QEvent * event ); }; /// WXWidget support: draw to wxImage class CRQtScreen : public CRGUIScreenBase { public: MainWindow * _window; protected: int _bufDepth; virtual void update( const lvRect & a_rc, bool full ) { lvRect rc(a_rc); CRLog::debug("update screen, bpp=%d width=%d, height=%d, rect={%d, %d, %d, %d} full=%d", _bufDepth, getWidth(),getHeight(), (int)rc.left, (int)rc.top, (int)rc.right, (int)rc.bottom, full?1:0 ); // TODO if ( rc.isEmpty() ) return; _window->update(rc.left, rc.top, rc.width(), rc.height() ); } public: /// creates compatible canvas of specified size virtual LVDrawBuf * createCanvas( int dx, int dy ) { // bufDepth LVDrawBuf * buf; if (_bufDepth==32) buf = new LVColorDrawBuf( dx, dy ); else buf = new LVGrayDrawBuf( dx, dy, _bufDepth ); buf->Clear(0xFFFFFF); return buf; } virtual ~CRQtScreen() { } CRQtScreen( MainWindow * window, int width, int height, int bufDepth ) : CRGUIScreenBase( 0, 0, true ), _window(window), _bufDepth(bufDepth) { _width = width; _height = height; //CRLog::info( "Device depth=%d, will use rendering depth=%d", (int)im->depth, d ); _canvas = LVRef<LVDrawBuf>( createCanvas( _width, _height ) ); _front = LVRef<LVDrawBuf>( createCanvas( _width, _height ) ); printf("Created screen %d x %d, depth = %d\n", _width, _height, _bufDepth ); } }; int EV_PROCESS_CRGUI_EVENTS; class CRQtWindowManager : public CRGUIWindowManager { protected: MainWindow * _window; public: CRQtWindowManager( int dx, int dy, int bufDepth ) : CRGUIWindowManager(NULL) { EV_PROCESS_CRGUI_EVENTS = QEvent::registerEventType(); _window = new MainWindow(this); _window->setGeometry(0, 0, dx, dy); CRQtScreen * s = new CRQtScreen( _window, dx, dy, bufDepth ); _screen = s; _ownScreen = true; _window->show(); // cr_rotate_angle_t angle = readXCBScreenRotationAngle(); // if ( angle!=0 ) // CRLog::info("Setting rotation angle: %d", (int)angle ); // setScreenOrientation( angle ); } /// returns true if key is processed virtual bool onKeyPressed( int key, int flags = 0 ) { return CRGUIWindowManager::onKeyPressed( key, flags ); } virtual bool getBatteryStatus( int & percent, bool & charging ); /// idle actions virtual void idle(); // runs event loop virtual int runEventLoop(); /// forward events from system queue to application queue virtual void forwardSystemEvents( bool waitForEvent ); virtual void nextEvent() { QEvent * event = new QEvent(QEvent::User); QApplication::postEvent(_window, event); } virtual void postEvent( CRGUIEvent * event ) { CRGUIWindowManager::postEvent( event ); nextEvent(); } }; class QtDocViewWin : public V3DocViewWin { public: /// file loading is finished successfully - drawCoveTo() may be called there virtual void OnLoadFileEnd() { V3DocViewWin::OnLoadFileEnd(); //((CRQtWindowManager*)_wm)->updateProperties(); } QtDocViewWin( CRGUIWindowManager * wm, lString16 dataDir ) : V3DocViewWin( wm, dataDir ) { } virtual ~QtDocViewWin() { } }; void MainWindow::paintEvent ( QPaintEvent * event ) { QPainter painter(this); QRect rc = rect(); LVRef<LVDrawBuf> buf = _wm->getScreen()->getCanvas(); int dx = buf->GetWidth(); int dy = buf->GetHeight(); if ( dx>rc.width() ) dx=rc.width(); if ( dy>rc.height() ) dy=rc.height(); if ( buf->GetBitsPerPixel()==16 ) { QImage img(dx, dy, QImage::Format_RGB16 ); for ( int i=0; i<dy; i++ ) { unsigned char * dst = img.scanLine( i ); unsigned char * src = buf->GetScanLine(i); for ( int x=0; x<dx; x++ ) { *dst++ = *src++; *dst++ = *src++; // *dst++ = *src++; // *dst++ = 0xFF; // src++; } } painter.drawImage( rc, img ); } else if ( buf->GetBitsPerPixel()==32 ) { QImage img(dx, dy, QImage::Format_RGB32 ); for ( int i=0; i<dy; i++ ) { unsigned char * dst = img.scanLine( i ); unsigned char * src = buf->GetScanLine(i); for ( int x=0; x<dx; x++ ) { *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = 0xFF; src++; } } painter.drawImage( rc, img ); } else if ( buf->GetBitsPerPixel()==4 ) { QImage img(dx, dy, QImage::Format_RGB32 ); for ( int i=0; i<dy; i++ ) { unsigned char * dst = img.scanLine( i ); unsigned char * src = buf->GetScanLine(i); for ( int x=0; x<dx; x++ ) { lUInt8 b = *src++; *dst++ = b; *dst++ = b; *dst++ = b; *dst++ = 0xFF; } } painter.drawImage( rc, img ); } } void MainWindow::keyPressEvent ( QKeyEvent * event ) { } void MainWindow::resizeEvent ( QResizeEvent * event ) { QSize sz = event->size(); CRLog::debug("resizeEnvent(%d, %d)", sz.width(), sz.height()); _wm->reconfigure(sz.width(), sz.height(), CR_ROTATE_ANGLE_0); } void MainWindow::customEvent ( QEvent * event ) { CRLog::debug("customEvent"); //if ( event->) _wm->processPostedEvents(); } void MainWindow::wheelEvent ( QWheelEvent * event ) { } void MainWindow::mouseMoveEvent ( QMouseEvent * event ) { } void MainWindow::mousePressEvent ( QMouseEvent * event ) { } void MainWindow::mouseReleaseEvent ( QMouseEvent * event ) { } bool CRQtWindowManager::getBatteryStatus( int & percent, bool & charging ) { percent = 100; charging = false; return false; } /// forward events from system queue to application queue void CRQtWindowManager::forwardSystemEvents( bool waitForEvent ) { if ( _stopFlag ) waitForEvent = false; } /// called when message queue is empty and application is going to wait for event void CRQtWindowManager::idle() { if ( !_stopFlag && getWindowCount() ) { } } // runs event loop int CRQtWindowManager::runEventLoop() { return QCoreApplication::instance()->exec(); } int main(int argc, char **argv) { int res = 0; { CRLog::setStdoutLogger(); #ifdef _DEBUG // __i386__ CRLog::setLogLevel( CRLog::LL_TRACE ); #else //CRLog::setLogLevel( CRLog::LL_ERROR ); InitCREngineLog("/home/user/.crengine/crlog.ini"); #endif // gettext initialization setlocale (LC_ALL, ""); #undef LOCALEDIR #define LOCALEDIR "/usr/share/locale" #ifndef PACKAGE #define PACKAGE "cr3" #endif const char * bindres = bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); CRLog::info("Initializing gettext: dir=%s, LANGUAGE=%s, DOMAIN=%s, bindtxtdomain result = %s", LOCALEDIR, getenv("LANGUAGE"), PACKAGE, bindres); CRLog::info("Trying to translate: 'On'='%s'", gettext("On")); CRLog::info("Trying to translate: 'About...'='%s'", gettext("About...")); lString16Collection fontDirs; //fontDirs.add( lString16(L"/usr/local/share/cr3/fonts") ); //fontDirs.add( lString16(L"/usr/local/share/fonts/truetype/freefont") ); //fontDirs.add( lString16(L"/mnt/fonts") ); //fontDirs.add( lString16(L"/usr/share/fonts/truetype") ); //fontDirs.add( lString16(L"/usr/share/fonts/truetype/liberation") ); //fontDirs.add( lString16(L"/usr/share/fonts/truetype/freefont") ); //fontDirs.add( lString16(L"/root/fonts/truetype") ); if ( !InitCREngine( argv[0], fontDirs ) ) { printf("Cannot init CREngine - exiting\n"); return 2; } if ( argc<2 ) { printf("Usage: cr3 <filename_to_open>\n"); return 3; } const char * fname = argv[1]; const char * bmkdir = NULL; if ( !strcmp(fname, "unittest") ) { runCRUnitTests(); return 0; } lString8 fn8( fname ); lString16 fn16 = LocalToUnicode( fn8 ); CRLog::info("Filename to open=\"%s\"", LCSTR(fn16) ); if ( fn8.startsWith( lString8("/media/sd/") ) ) bmkdir = "/media/sd/bookmarks/"; QApplication app(argc, argv); //TODO: remove hardcoded int bitDepth = 4; //TODO #ifdef __i386__ CRQtWindowManager winman( 600, 680, bitDepth ); #else CRQtWindowManager winman( 600, 800, bitDepth ); #endif if ( !ldomDocCache::init( lString16("/media/sd/.cr3/cache"), 0x100000 * 64 )) ldomDocCache::init( lString16("/tmp/.cr3/cache"), 0x100000 * 64 ); /*64Mb*/ { lString16 home = Utf8ToUnicode(lString8(( getenv("HOME") ) )); lString16 homecrengine = home + "/.crengine/"; lString8 home8 = UnicodeToUtf8( homecrengine ); const char * keymap_locations [] = { "/etc/cr3", "/usr/share/cr3", home8.c_str(), "/media/sd/crengine/", NULL, }; loadKeymaps( winman, keymap_locations ); if (!winman.loadSkin(homecrengine + "skin")) if (!winman.loadSkin(lString16("/media/sd/crengine/skin"))) winman.loadSkin(lString16("/usr/share/cr3/skins/default")); { const lChar16 * imgname = ( winman.getScreenOrientation()&1 ) ? L"cr3_logo_screen_landscape.png" : L"cr3_logo_screen.png"; LVImageSourceRef img = winman.getSkin()->getImage(imgname); if ( !img.isNull() ) { winman.getScreen()->getCanvas()->Draw(img, 0, 0, winman.getScreen()->getWidth(), winman.getScreen()->getHeight(), false ); } } HyphMan::initDictionaries(lString16("/usr/share/cr3/hyph/")); //LVExtractPath(LocalToUnicode(lString8(fname))) main_win = new QtDocViewWin( &winman, lString16(CRSKIN) ); main_win->getDocView()->setBackgroundColor(0xFFFFFF); main_win->getDocView()->setTextColor(0x000000); main_win->getDocView()->setFontSize( 20 ); if ( !main_win->loadDefaultCover( lString16("/media/sd/crengine/cr3_def_cover.png") ) ) main_win->loadDefaultCover( lString16("/usr/share/cr3/cr3_def_cover.png") ); if ( !main_win->loadCSS( lString16("/media/sd/crengine/fb2.css") ) ) main_win->loadCSS( lString16("/usr/share/cr3/fb2.css") ); if ( !main_win->loadDictConfig( lString16("/media/sd/crengine/dict/dictd.conf") ) ) main_win->loadDictConfig( lString16("/usr/share/cr3/dict/dictd.conf") ); if ( bmkdir!=NULL ) main_win->setBookmarkDir( lString16(bmkdir) ); #define SEPARATE_INI_FILES CRLog::trace("choosing init file..."); const lChar16 * ini_fname = L"cr3.ini"; #ifdef SEPARATE_INI_FILES if ( strstr(fname, ".txt")!=NULL || strstr(fname, ".tcr")!=NULL) { ini_fname = L"cr3-txt.ini"; } else if ( strstr(fname, ".rtf")!=NULL ) { ini_fname = L"cr3-rtf.ini"; } else if ( strstr(fname, ".htm")!=NULL ) { ini_fname = L"cr3-htm.ini"; } else if ( strstr(fname, ".epub")!=NULL ) { ini_fname = L"cr3-epub.ini"; } else { ini_fname = L"cr3-fb2.ini"; } #endif const lChar16 * dirs[] = { L"/media/sd/crengine/", homecrengine.c_str(), NULL }; int i; CRLog::debug("Loading settings..."); lString16 ini; for ( i=0; dirs[i]; i++ ) { ini = lString16(dirs[i]) + ini_fname; if ( main_win->loadSettings( ini ) ) { break; } } CRLog::debug("settings at %s", UnicodeToUtf8(ini).c_str() ); lString16 hist; for ( i=0; dirs[i]; i++ ) { hist = lString16(dirs[i]) + "cr3hist.bmk"; if ( main_win->loadHistory( hist ) ) { break; } } #if 0 static const int acc_table[] = { XK_Escape, 0, MCMD_QUIT, 0, XK_Return, 0, MCMD_MAIN_MENU, 0, '0', 0, DCMD_PAGEDOWN, 0, XK_Down, 0, DCMD_PAGEDOWN, 0, '9', 0, DCMD_PAGEUP, 0, #ifdef WITH_DICT '2', 0, MCMD_DICT, 0, #endif XK_Up, 0, DCMD_PAGEUP, 0, '+', 0, DCMD_ZOOM_IN, 0, '=', 0, DCMD_ZOOM_IN, 0, '-', 0, DCMD_ZOOM_OUT, 0, '_', 0, DCMD_ZOOM_OUT, 0, 0 }; main_win->setAccelerators( CRGUIAcceleratorTableRef( new CRGUIAcceleratorTable( acc_table ) ) ); #endif winman.activateWindow( main_win ); if ( !main_win->loadDocument( LocalToUnicode((lString8(fname))) ) ) { printf("Cannot open book file %s\n", fname); res = 4; } else { winman.nextEvent(); winman.runEventLoop(); } } } HyphMan::uninit(); ldomDocCache::close(); ShutdownCREngine(); return res; }