LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Blogs > rainbowsally
User Name
Password

Notices

Rate this Entry

ui-tools implementation (ui-tools.cpp)

Posted 12-15-2012 at 09:57 AM by rainbowsally
Updated 12-15-2012 at 08:29 PM by rainbowsally (linkage to first part + parag alignment fixed)

ui-tools implementation (ui-tools.cpp)

The following changes are in the code below, but are listed in case you already have the file and want to fix it yourself (and see the context of the problem).

Changelog Dec 15 2012 (second prob)
"Unknown error" msg issued when it's not an error.

Here's the fix. Whenever we call
Code:
  ok = find_slots(...);
we need to return 'true' without acting on the return values but not return 'false' as was done in the original.

Around lines (after applying first fix below)
217, 269, 290
change:
Code:
 
  if(!ok)
  //    return false;
  return true; // no slots, not an error -rs
Changelog Dec 15 2012
Note: This may or may not be the final fix.

Remove redundant semicolons in slot names for writeH and writeCpp switches.
Code:
In ui-tool.cpp around line 389 change:
        // let caller decide whether to use the trailing semicolon -rs
        // obj.op += sprintf(obj.op, " arg%c);", param_id++);
        obj.op += sprintf(obj.op, " arg%c)", param_id++);




Implementation file for ui-tools (see the next blog entry here http://www.linuxquestions.org/questi...tilites-35207/ ) and the makefile definitions (see mc2 download here at the blog).

file: src/ui-tool.cpp
purpose: source file
Code:
// ui-tool.cpp
/*
 *   sortSlots \$UIFILE
 *    sorts the slots in a ui file for easier lookups of slots 
 *    in the signal slot editor
 * 
 *  writeCpp \$UIFILE
 *    writes slot templates for the file named like the $UIFILE
 *    but with the '.cpp' file extension.
 *    
 *  writeH \$UIFILE
 *    writes slot templates for the file named like the $UIFILE
 *    but with the '.h' file extension.
 * 
 *  listSlots \$UIFILE
 *    Shows slots found in the \$UIFILE
 * 
 *  listSignals \$UIFILE
 *    Shows signals found in the \$UIFILE
 * 
 *  commands
 *    shows this list and usage notes.
 * 
 *  help
 *    Displays a simple help message in a message box
 */

#include <QMessageBox>
#include <QDesktopWidget>
#include <QApplication>
#include <LQ-qt/SList.h>
#include <stdio.h> // printf()
#include <ctype.h> // char stuff
#include <string.h> // memcmp()
#include "dict-util.h" // help lookups

#define version "1.0"

#define NO_PARSER_WARN 1
#include <LQ-qt/Parser.h>

using namespace Parser;

// to avoid the name mangling
extern "C"
{

void centerWindow(QWidget* window)
{
  // Unreliable if window isn't shown yet
  if(!window->isVisible()) return;
  
  int dtx,dty,dtw,dth;
  int winx,winy,winw,winh;
  int x, y;
  
  QDesktopWidget* dt = qApp->desktop();
  dt->availableGeometry().getRect(&dtx,&dty,&dtw,&dth);
  window->geometry().getRect(&winx,&winy,&winw,&winh);
  
  x = dtx + dtw/2 - winw/2; // x1 should not always be 0
  y = dty + dth/2 - winh/2; // y1 ""
  
  window->setGeometry(x, y, winw, winh);
  qApp->processEvents();
}


void doMsg(QMessageBox* b)
{
  b->setWindowFlags(Qt::WindowStaysOnTopHint);
  b->show();
  centerWindow(b);
  b->exec();
}

// requires instance of QApplication in main()
void errorMsg(const char* msg)
{  
  QMessageBox* b = new QMessageBox(QMessageBox::Critical, "Error", msg,
                                   QMessageBox::Ok, NULL);
  doMsg(b);
}

// requires instance of QApplication in main()
void warnMsg(const char* msg)
{
  QMessageBox* b = new QMessageBox(QMessageBox::Warning, "Error", msg,
                                   QMessageBox::Ok, NULL);
  doMsg(b);
}

// requires instance of QApplication in main()
void infoMsg(const char* msg)
{
  QMessageBox* b = new QMessageBox(QMessageBox::Information, "Notice", msg,
                                   QMessageBox::Ok);
  doMsg(b);
}


int usage(int errcode)
{
#include "uitool_str.dat"
  if(errcode)
    errorMsg(uitools_str);
  else
    infoMsg(uitools_str);
  return errcode;
}

void TODO(const char* funcname)
{
  char buf[256];
  sprintf(buf, 
          "%s is not yet implemented.\n"
          "For now, you may have to use a text\n"
          "editor and do this operation manually.\n"
          , funcname);
  errorMsg(buf);
  exit(1);
}

// finds the open and close of the tag in line and copies 
// what's between to a buffer, returns true on success.
bool parse_tag(char* buf, const char* tag, const char* line)
{
  bool ret = false;
  PARSER_OBJ o;
  PARSER_OBJ *prev =
  parser_init(
                          &o,               /// addr of object to use
                          line,             /// initialized text to parse
                          strlen(line) + 1, /// exact length including terminating null
                          false      /// whether or not we can free inbuffer when done
                         );
  // .* <tag><VALUE</tag> .*
  while(1)
  {
    SAVE_PTRS();
    if(obj_is_eoi())
    {
      obj.state = false;
      break;
    }
    do
    {
        (
          obj_skip("<") 
          && obj_skip(tag)
          && obj_skip(">")
          && obj_copy_to("</")
          && obj_skip("</")
          // value_len = ip - value // but we don't need it
          && obj_skip(tag)
          && obj_skip(">")
        );
               
      if(!obj.state) break;
      
      // all tests passed
      strcpy(buf, obj.obuf);
    }while(0); // unnest
    
    if(obj.state) break;
    else
    {
      RESTORE_PTRS();
      obj_skip_nchars(1);
    }
  }// while 1
  ret = obj.state;
  parser_free(&o, prev);
  return ret;
}

// sets pointers to the lines with the tags <slots> and </slots>
// and returns true if successful, else false.
bool find_slots(SList* pxml, int* ptag_start, int* ptag_end)
{
  int start = -1, end = -1;
  
  for(int i = 1; i < pxml->count(); i++)
  {
    char* line = pxml->get(i);
    if(strstr(line, "<slots>"))
      start = i;
    else if(strstr(line, "</slots>"))
    {
      if(start < 0)
        break; // error, forget it.
      end = i;
      break;
    }
  }
  *ptag_start = start;
  *ptag_end = end;  
  
  if((start | end) < 0)
    return false;
  else
    return true;
}

// slots are all continguous inside the <slots> ... </slots> tags
static bool _get_slots(const char* filename, SList* pslots)
{
  bool ok;
  char buf[256];
  SList tmp;
  tmp.fileRead(filename);
  if(!tmp.count())
    return false;
  
  int tag_start, tag_end;
  ok = find_slots(&tmp, &tag_start, &tag_end);
  if(!ok)
  //    return false;
  return true; // no slots, not an error -rs
  
  for(int i = tag_start + 1; i < tag_end; i++)
  {
    char* line = tmp.get(i);
    if(parse_tag(buf, "slot", line))
      pslots->append(buf);
  }
  return true;
}


// signals can be anywhere in the file and may be duplicated several times.
static bool _get_signals(const char* filename, SList *s, SList *signal)
{
  char buf[256];
  s->fileRead(filename);
  if(!s->count())
    return false;
  
  for(int i = 1; i < s->count(); i++)
  {
    char* line = s->get(i);
    if(parse_tag(buf, "signal", line))
    {
      // find in dup in string
      bool state = true;
      for(int ii = 0; ii < signal->count(); ii++)
      {
        if(strcmp(signal->get(ii), buf) == 0)
        {
          state = false;
          break;
        }
      }
      if(state)
        signal->append(buf);
    }
  }
  return true;
}


bool moveSlots(SList* pslots, SList* pxml)
{
  bool ok;
  int tag_start, tag_end;
  ok = find_slots(pxml, &tag_start, &tag_end);
  if(!ok)
  //    return false;
  return true; // no slots, not an error -rs
  
  int first_tag = tag_start + 1;
  for(int i = first_tag; i < tag_end; i++)
  {
    // continue moving and removing until count is done
    pslots->append(pxml->get(first_tag));
    pxml->remove(first_tag);
  }
  return true;
}

bool insertSlots(SList* pxml, SList* pslots)
{
  // pxml MUST still have the tags for the slots whether or not
  // the slots have been moved/removed.
  bool ok;
  int tag_start, tag_end;
  ok = find_slots(pxml, &tag_start, &tag_end);
  if(!ok)
  //    return false;
  return true; // no slots, not an error -rs
  
  int insloc = tag_start + 1; // where we'll be inserting
  for(int i = pslots->count() -1; i >= 0; i--)
    pxml->insert(pslots->get(i), insloc);
  return true;
}

bool sortSlots(const char* filename)
{
#warning needs backup
  bool ret;
  char swapbuf[256];
  SList xnames;
  SList xml;
  SList names;
  
  xml.fileRead(filename);
  if(!xml.count())
    return false;
  
  ret = moveSlots(&xnames, &xml);
  if(!ret)
    return false;
  
  // xnames is the xml containing the names
  
  ret = _get_slots(filename, &names);
  // names is the alpha-sortable string
   
  // bool find_slots(SList* pxml, int* ptag_start, int* ptag_end)
  bool changed = true;
  while(changed)
  {
    changed = false;
    for(int i = 1; i < names.count(); i++)
    {
      if(strcmp(names.get(i), names.get(i-1)) < 0) // swap 'em?
      {
        // swap both sets of names
        names.insert(names.get(i), i-1);
        names.remove(i+1);
        xnames.insert(xnames.get(i), i-1);
        xnames.remove(i+1);
        changed = true;
      }
    }
  }
  
  ret = insertSlots(&xml, &xnames);
  if(!ret)
    return false;
  
//  xml.fileWrite(filename);
  for(int i = 0; i < xml.count(); i++) 
    printf("%s\n", xml.get(i));
    
  return true;
}

// input is a slot name as output from listSlots, with no
// tags and no parameter names.
static bool _xlate_slot(char* buf, int bufmax, const char* slotname)
{
  bool ret;
  char param_name[256];
  int param_id = 'A';
  PARSER_OBJ o;
  PARSER_OBJ* prev = 
      parser_init(&o, slotname, strlen(slotname), false);
  do
  {
    obj_copy_to("(");
    if(!obj.state) break;
    obj_copy("(");
    if(obj_is(")")) // empty list
    {
      obj_copy(")");
      break; // true
    }
    // else has parameters
    // for every , and ')' insert a space and a param name
    while(1)
    {
      if(obj_is_eoi())
      {
        obj.state = false;
        break;
      }
      if(obj_copy_to(","))
      {
        obj_skip(",");
        obj.op += sprintf(obj.op, " arg%c,", param_id++);
        // and continue
      }
              
      else if(obj_copy_to(")"))
      {
        obj_skip(")");
        // let caller decide whether to use the trailing semicolon -rs
        // obj.op += sprintf(obj.op, " arg%c);", param_id++);
        obj.op += sprintf(obj.op, " arg%c)", param_id++);
        
        // break
        break;
      }
      else
        obj.state = false;
      break;
    }
  }while(0);
  if((ret = obj.state))
  {    
    strcpy(buf, obj.obuf);
  }
  ret = obj.state;
  parser_free(&o, prev);
  return ret;
}

static bool _get_classname(const char* filename, SList* c)
{
  char buf[256];
  SList x;
  x.fileRead(filename);
  
  // quick and dirty, really needs more checking TODO:
  char* line = x.get(2); // <class>Name</class>
  char* op;
  char* ip = strstr(line, "<class>");
  if(!ip)
    return false;
  
  ip += 7;
  op = buf;
  while(*ip != '<')
    *op++ = *ip++;
  *op = 0;
  c->append(buf);
  return true;
}

bool writeCpp(const char* filename)
{
  bool ok;
  SList s;
  SList c;
  
  ok = _get_slots(filename, &s);
  if(!ok)
    return false;
  
  ok = _get_classname(filename, &c);
  if(!ok)
    return false;
  
  /////////////////////////////////////
  // c@0 = classname
  char* p;
  char bname[256];
  sprintf(bname, filename);
  p = strrchr(bname, '.');
  if(p) *p = 0;
  printf("\n// Place in %s.cpp\n", bname);
  for(int i = 0; i < s.count(); i++)
  {
    char slotname[256];
    _xlate_slot(slotname, 256, s.get(i));
    printf("void %s::%s\n", c.get(0), slotname);
    printf("{\n#warning Not Implemented Yet!\n}\n\n");
  }  
  return true;
}


bool writeH(const char* filename)
{
  //  #warning writes slots per uiname.h
  bool ok;
  SList s;
  ok = _get_slots(filename, &s);
  if(!ok)
    return false;
  
  /////////////////////////////////////
  char* p;
  char bname[256];
  sprintf(bname, filename);
  p = strrchr(bname, '.');
  if(p) *p = 0;
  printf("\n// Place below Q_OBJECT in %s.h\n", bname);
  printf("\npublic slots:\n");  
  for(int i = 0; i < s.count(); i++)
  {
    char slotname[256];
    _xlate_slot(slotname, 256, s.get(i));
    printf("  void %s;\n", slotname);
  }  
  return true;
}


// just show the list of slots in the ui file.
bool listSlots(const char* filename)
{
  bool ok;  
  SList s;
  ok = _get_slots(filename, &s);
  if(ok)
  {
    for(int i = 0; i < s.count(); i++)
      printf("%s\n", s.get(i));
  }
  return ok;
}
  

bool listSignals(const char* filename)
{
  bool ret;
  SList s;
  SList signal;
  ret = _get_signals(filename, &s, &signal);
  if(ret)
  {
    for(int i = 0; i < signal.count(); i++)
      printf("%s\n", signal.get(i));
  }
  return ret;
}


bool printVersion()
{
  printf("ui-tool version %s\n", version);
  return true;
}

bool commands()
{
  show_command_help();
  return true;
}

bool help()
{
  usage(0);
  return true;
}

} // extern "C"

file: mc2.def
purpose: source file
Code:
# mc2.def template created with Makefile Creator 'mc2'

#########################################################################################
# for a bit more QT support use 'mc2 -fetch qt4' and add -lLQ-qt, PREFIX, etc. as needed.

## sandbox path and other new variables
PREFIX = $(HOME)/usr32

## The output file name not including path
OUTNAME = ui-tool

## The directories for sources, (temp) objects, and binary output(s)
BINDIR = .
SRCDIR = src
OBJDIR = o

## What COMPILE should do.
COMPILE = g++ -m32 -c -o
#CFLAGS = -g3
CFLAGS = -O2 # or -g3
INCLUDE = -I/usr/include -I$(PREFIX)/include -I./$(SRCDIR) -I/usr/include/QtGui -I/usr/include/Qt

## What LINK should do.
LINK = g++ -m32 -o
LDFLAGS = -lQtGui -lLQ-qt

# to make a statically linked version replace -lLQ-qt (above) 
# with the full path to the static lib such as:
#   $(PREFIX)/lib/libLQ-qt.a # <-- static link this one

LIB = -L/usr/lib -L$(PREFIX)/lib

################################################################
## User Defined Targets

clean:
  @rm -f $(MAIN)
  @rm -f $(OBJ)
  @rm -f *~ */*~ */*/*~ */*/*/*~

force: # used to force execution
This one really DOES require LQ-qt-mc2. This really ain't going to happen unless you at least have the lib, but then you'd also have mc2. ;-)

- The Computer Mad Science Team

:-)
Posted in Uncategorized
Views 586 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 07:40 AM.

Main Menu
Advertisement

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration