Logo Search packages:      
Sourcecode: gambas version File versions  Download package

main.cpp

/***************************************************************************

  main.cpp

  The interface between the QT plug-in and the Gambas interpreter

  (c) 2000-2003 Beno� Minisini <gambas@users.sourceforge.net>

  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 1, or (at your option)
  any later version.

  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.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/

#define __MAIN_CPP

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include "gambas.h"

#define QT_THREAD_SUPPORT
#include <qapplication.h>

#include <qtooltip.h>

#include <qmessagebox.h>
#include <qclipboard.h>
#include <qstring.h>

#include <qmap.h>
#include <qmime.h>
#include <qfileinfo.h>
#include <qbuffer.h>
#include <qwidgetlist.h>
#include <qevent.h>
#include <qtextcodec.h>

#if QT_VERSION >= 0x030100
  #include <qeventloop.h>
#endif

#include "gb.qt.h"

#include "CFont.h"
#include "CScreen.h"
#include "CWidget.h"
#include "CWindow.h"
#include "CButton.h"
#include "CContainer.h"
#include "CLabel.h"
#include "CListBox.h"
#include "CTextBox.h"
#include "CTextArea.h"
#include "CPictureBox.h"
#include "CMenu.h"
#include "CPanel.h"
#include "CMouse.h"
#include "CKey.h"
#include "CColor.h"
#include "CConst.h"
#include "CCheckBox.h"
#include "CFrame.h"
#include "CRadioButton.h"
#include "CTreeView.h"
#include "CIconView.h"
#include "CGridView.h"
#include "CTabStrip.h"
#include "CDialog.h"
#include "CPicture.h"
#include "CImage.h"
#include "CDrawing.h"
#include "CClipboard.h"
#include "CDraw.h"
#include "CTimer.h"
#include "CWatch.h"
#include "CScrollView.h"
#include "CDrawingArea.h"
#include "CProgress.h"
#include "CMessage.h"
#include "CPrinter.h"

#include "main.h"

/*#define DEBUG*/

extern "C" {

GB_INTERFACE GB;

}

int MAIN_in_wait = 0;
int MAIN_loop_level = 0;

static bool in_event_loop = false;


/***************************************************************************

  MyMimeSourceFactory

  Create a QMimeSourceFactory to handle files stored in an archive

***************************************************************************/

class MyMimeSourceFactory: public QMimeSourceFactory
{
public:

  MyMimeSourceFactory();

  virtual const QMimeSource* data(const QString& abs_name) const;

private:

  QMap<QString, QString> extensions;
};


MyMimeSourceFactory::MyMimeSourceFactory()
{
  extensions.replace("htm", "text/html;charset=iso8859-1");
  extensions.replace("html", "text/html;charset=iso8859-1");
  extensions.replace("txt", "text/plain");
  extensions.replace("xml", "text/xml;charset=UTF-8");
  extensions.replace("jpg", "image/jpeg");
  extensions.replace("png", "image/png");
  extensions.replace("gif", "image/gif");
}


const QMimeSource* MyMimeSourceFactory::data(const QString& abs_name) const
{
  char *addr;
  long len;
  QStoredDrag* sr = 0;
  char *path;

  //qDebug("MyMimeSourceFactory::data: %s", (char *)abs_name.latin1());

  path = (char *)abs_name.latin1();

  if (true) //abs_name[0] != '/')
  {
    if (GB.LoadFile(path, 0, &addr, &len))
      GB.Error(NULL);
    else
    {
      QByteArray ba;
      ba.setRawData((const char *)addr, len);

      QFileInfo fi(abs_name);
      QString e = fi.extension(FALSE);
      QCString mimetype = "application/octet-stream";

      const char* imgfmt;

      if ( extensions.contains(e) )
        mimetype = extensions[e].latin1();
      else
      {
        QBuffer buffer(ba);

        buffer.open(IO_ReadOnly);
        if (( imgfmt = QImageIO::imageFormat( &buffer ) ) )
          mimetype = QCString("image/")+QCString(imgfmt).lower();
        buffer.close();
      }

      sr = new QStoredDrag( mimetype );
      sr->setEncodedData( ba );

      ba.resetRawData((const char*)addr, len);

      //qDebug("MimeSource: %s %s", abs_name.latin1(), (const char *)mimetype);

      GB.ReleaseFile(&addr, len);
    }
  }

  return sr;
}

static MyMimeSourceFactory myMimeSourceFactory;


/***************************************************************************

  MyEventLoop

  Manage window deletion

***************************************************************************/

class MyEventLoop : public QEventLoop
{
public:
  MyEventLoop();
  virtual bool processEvents( ProcessEventsFlags flags );
};

MyEventLoop::MyEventLoop()
: QEventLoop()
{
}

bool MyEventLoop::processEvents(ProcessEventsFlags flags)
{
  bool ret;
  CWIDGET **ptr;
  CWIDGET *ob;

  MAIN_loop_level++;
  ret = QEventLoop::processEvents(flags);
  MAIN_loop_level--;

  ptr = &CWIDGET_destroy_list;

  for(;;)
  {
    ob = *ptr;
    if (!ob)
      break;

    if (MAIN_loop_level <= ob->level)
    {
      //qDebug(">> delete %p (%p) :%p:%ld", ob, ob->widget, ob->ob.klass, ob->ob.ref);
      //*ptr = ob->next;
      delete ob->widget;
      //GB.Unref((void **)&ob);
      //qDebug("   delete %p (%p) :%p:%ld #2", ob, ob->widget, ob->ob.klass, ob->ob.ref);
      //qDebug("<< delete %p (%p)", ob, ob->widget);
    }
    else
    {
      ptr = &ob->next;
    }
  }

  return ret;
}


/***************************************************************************/

static bool must_quit(void)
{
  /*
  QPtrDictIterator<CWINDOW> iter(CWindow::dict);
  int n;
  CWINDOW *win;

  n = 0;
  while ((win = iter.current()))
  {
    if (QWIDGET(win)->isVisible())
      n++;

    ++iter;
  }
  */

  //qDebug("CWindow::count = %d  CWatch::count = %d  in_event_loop = %d",
  //  CWindow::count, CWatch::count, in_event_loop);

  return CWindow::count == 0 && CWatch::count == 0 && in_event_loop;
}

void MAIN_check_quit(void)
{
  if (must_quit())
  {
    //qDebug("Must quit !");
    //while (qApp->eventLoop()->hasPendingEvents())
    //  qApp->eventLoop()->processEvents(QEventLoop::AllEvents);
    qApp->syncX();
    qApp->exit();
  }
}


static void QT_InitEventLoop(void)
{
  new MyEventLoop();
}

static void QT_Init(void)
{
  static bool init = false;
  QFont f;

  if (init)
    return;

  /*fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, FD_CLOEXEC);*/
  QMimeSourceFactory::addFactory(&myMimeSourceFactory);

  //f = QApplication::font();
  //f.setPointSizeFloat((double)f.pointSize() * 96.0 / (double)QPaintDevice::x11AppDpiX());
  //qDebug("Default font size = %g", f.pointSizeFloat());
  //QApplication::setFont(f);

  //QPaintDevice::x11SetAppDpiX(96);
  //QPaintDevice::x11SetAppDpiY(96);

  //f = QToolTip::font();
  //f.setPointSize(f.pointSize() - ((f.pointSize() - 1) / 6 + 1));
  //QToolTip::setFont(f);

  // It does not work, why ?
  //QTranslator qt( 0 );
  //qDebug("Loading translator %s", (QString("qt_") + QTextCodec::locale()).latin1());
  //qt.load(QString("qt_") + "fr", "/usr/lib/qt3/translations");
  //qApp->installTranslator( &qt );

  #if USE_QT_TRANSLATION
  qt = new QTranslator(qApp);
  if (qt->load(QString( "qt_") + QTextCodec::locale(), QString(getenv("QTDIR")) + "/translations"))
    qApp->installTranslator(qt);
  #endif

  init = true;
}


static void my_main(int *argc, char **argv)
{
  QT_InitEventLoop();
  new QApplication(*argc, argv);
  #if QT_VERSION <= 0x030005
  qApp->unlock();
  #endif
  //qApp->setStyle("windows");
  QT_Init();
}


static int my_loop()
{
  int ret = 0;

  in_event_loop = true;

  if (!must_quit())
    ret = qApp->exec();

  //qDebug("Exit event loop");

  return ret;
}


static void my_wait(long duration)
{
  MAIN_in_wait++;
  #if QT_VERSION >= 0x030100
    if (duration > 0)
      qApp->eventLoop()->processEvents(QEventLoop::AllEvents, duration);
    else
      qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput, duration);
  #else
    qApp->processEvents(duration);
  #endif
  MAIN_in_wait--;
}


static void my_watch(int fd, int type, void *callback, long param)
{
  CWatch::watch(fd, type, (GB_WATCH_CALLBACK)callback, param);
}


static void my_post(void)
{
  static MyPostCheck check;

  //qDebug("my_post ?");

  if (MyPostCheck::in_check)
    return;

  //qDebug("my_post !");

  MyPostCheck::in_check = true;
  QTimer::singleShot(0, &check, SLOT(check()));
}


static void my_quit()
{
  //QWidgetList *list;

  qApp->closeAllWindows();

  /*
  for(;;)
  {
    list = QApplication::topLevelWidgets();
    if (list->isEmpty())
      break;

    QApplication::postEvent(list->first(), new QEvent(EVENT_CLOSE));
    qApp->processEvents();
    delete list;
  }
  */

  //qApp->unlock();
}

static void my_error(int code, char *error, char *where)
{
  QString msg;

  CWatch::stop();
  qApp->exit();

  msg = "This application has raised an unexpected\nerror and must abort.\n\n[%1] %2.\n%3";
  msg = msg.arg(code).arg(error).arg(where);

  QMessageBox::critical(0, TO_QSTRING(GB.Application.Name()), msg);
}

static void QT_InitWidget(QWidget *widget, void *object)
{
  CWIDGET_new(widget, object);
}

static void *QT_GetObject(QWidget *widget)
{
  return CWidget::get((QObject *)widget);
}

static QWidget *QT_GetContainer(void *object)
{
  return CONTAINER(object);
}

static QPixmap *QT_GetPixmap(CPICTURE *pict)
{
  return pict->pixmap;
}

static QMimeSourceFactory *QT_MimeSourceFactory(void)
{
  return &myMimeSourceFactory;
}

const char *QT_ToUTF8(const QString &str)
{
  static QCString buf[UTF8_NBUF];
  static int cpt = 0;

  const char *res;

  buf[cpt] = str.utf8();
  res = (const char *)buf[cpt];
  cpt++;
  if (cpt >= UTF8_NBUF)
    cpt = 0;

  return res;
}

extern "C" {

GB_DESC *GB_CLASSES[] =
{
  CBorderDesc, CColorDesc, CAlignDesc, CArrangeDesc, CScrollDesc, CKeyDesc, CLineDesc, CFillDesc,
  CMessageDesc,
  CPictureDesc,
  CImageDesc,
  CDrawingDesc,
  CFontDesc, CFontsDesc,
  CMouseDesc, CCursorDesc,
  CClipboardDesc, CDragDesc,
  CDrawClipDesc, CDrawDesc, // apr� CFont !
  CDesktopDesc, CApplicationTooltipDesc, CApplicationDesc,
  CWidgetDesc, CChildrenDesc,
  CContainerDesc,
  CMenuChildrenDesc, CMenuDesc,
  CLabelDesc, CTextViewDesc, CPictureBoxDesc,
  CButtonDesc, CToggleButtonDesc, CToolButtonDesc,
  CCheckBoxDesc, CRadioButtonDesc,
  CTextBoxSelectionDesc, CTextBoxDesc, CComboBoxItemDesc, CComboBoxDesc,
  CTextAreaSelectionDesc, CTextAreaDesc,
  CListBoxItemDesc, CListBoxDesc,
  CListViewItemDesc, CListViewDesc,
  CTreeViewItemDesc, CTreeViewDesc,
  CColumnViewItemDesc, CColumnViewColumnDesc, CColumnViewColumnsDesc, CColumnViewDesc,
  CIconViewItemDesc, CIconViewDesc,
  CGridItemDesc, CGridRowDesc, CGridColumnDesc, CGridRowsDesc, CGridColumnsDesc,
  CGridViewDesc,
  CFrameDesc, CPanelDesc, CHBoxDesc, CVBoxDesc, CHPanelDesc, CVPanelDesc,
  CTabChildrenDesc, CTabDesc, CTabStripDesc,
  CScrollViewDesc,
  CDrawingAreaDesc,
  CProgressDesc,
  CWindowMenusDesc, CWindowDesc, CWindowsDesc, CFormDesc,
  CDialogDesc,
  CTimerDesc,
  CPrinterDesc,
  NULL
};

void *GB_QT_1[] = {

  (void *)1,

  (void *)QT_InitEventLoop,
  (void *)QT_Init,
  (void *)QT_InitWidget,
  (void *)QT_GetObject,
  (void *)QT_GetContainer,
  (void *)CWIDGET_border_simple,
  (void *)CWIDGET_border_full,
  (void *)CWIDGET_scrollbar,
  (void *)CFONT_create,
  (void *)QT_MimeSourceFactory,
  (void *)QT_GetPixmap,
  (void *)QT_ToUTF8,
  NULL
};


#if QT_VERSION >= 0x030304
static void myMessageHandler(QtMsgType type, const char *msg )
{
      if ((::strncmp(msg, "QMultiInputContext::", strlen("QMultiInputContext::")) == 0)
          || (::strncmp(msg, "sending IM", strlen("sending IM")) == 0))
            return;

      fprintf(stderr, "%s\n", msg);
      if (type == QtFatalMsg)
            abort();
}
#endif

int GB_INIT(void)
{
      #if QT_VERSION >= 0x030304
  qInstallMsgHandler(myMessageHandler);
  #endif

  GB.Hook(GB_HOOK_MAIN, (void *)my_main);
  GB.Hook(GB_HOOK_LOOP, (void *)my_loop);
  GB.Hook(GB_HOOK_WAIT, (void *)my_wait);
  GB.Hook(GB_HOOK_WATCH, (void *)my_watch);
  GB.Hook(GB_HOOK_POST, (void *)my_post);
  GB.Hook(GB_HOOK_QUIT, (void *)my_quit);
  GB.Hook(GB_HOOK_ERROR, (void *)my_error);

  /*GB.Declare(TheClasses);*/

  return TRUE;
}

void GB_EXIT()
{
  qApp->setStyle("windows");
  delete qApp;
}

}


/* class MyPostCheck */

bool MyPostCheck::in_check = false;

void MyPostCheck::check(void)
{
  //qDebug("MyPostCheck::check");
  in_check = false;
  GB.CheckPost();
}


Generated by  Doxygen 1.6.0   Back to index