· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
QT Programming Controls

2. Buttons,Containers,Views,Inputs :

생성한 윈도우에 여러 컨트롤들을 추가해보겠습니다.


buttons 간단한 버튼을 추가하도록 하겠습니다. 왼쪽 ToolBox탭에서 윈도우 Form으로 PushButton컨트롤을 끌어와 위치시킵니다.

s21.png
[PNG image (164.79 KB)]

버튼이 생성되었습니다. Name 속성을 변경하여 적당히 컨트롤의 객체 이름을 변경하고, Caption을 변경하여 버튼에 나타나난 텍스트를 변경합니다. 이제는 버튼이 눌러졌을 경우 메세지박스를 출력하도록 수정하겠습니다. 추가한 버튼에 마우스 오른쪽 버튼을 클릭하여 나온 메뉴에서 Connection을 선택하면 Signal-Slot을 설정할수 있는 창이 뜹니다.( F3을 누른 후 버튼을 선택해도 됩니다. )
s22.png
[PNG image (183.54 KB)]
F3키를 누른 상태에서 버튼을 클릭하였으면 Sender 와 Receiver가 버튼으로 설정됩니다. Signal을 보내는 객체는 버튼으로 설정하고 이벤트 핸들링을 할 객체는 윈도우 창으로 설정합니다. 버튼의 이름을 pushButton_hello 로 윈도우의 이름을 Form_Main이라면 Sender: pushButton_hello Signal: clicked() Receiver: Form_Main 으로 설정합니다. 이렇게 설정했다면 오른쪽에 Edit Slots...란 이름의 버튼이 생깁니다. 해당 버튼을 클릭하여 버튼이 클릭되었을 때 호출될 적절한 이벤트 핸들러를 생성할 수 있습니다.
s23.png
[PNG image (192.22 KB)]

new function을 눌러 새 slot을 생성하고 함수 이름을 적당히 교체합니다. 함수의 인자를 수정하면 해당 이벤트에 대한 슬롯으로 사용하지 못하므로 함수선언은 원본을 유지하도록 합니다. 확인을 누르고 다시 이전의 창으로 돌아아 Slot에 이전에 생성한 슬롯 함수를 고르고 확인을 누릅니다. 이제 Project Overview 창으로 놀아와 윈도우 창의 *.ui.h 파일을 선택합니다. 코드 창에 슬롯 함수가 생성되어 있는 것을 확인할 수 있습니다. 이 함수의 내부에 처리할 기능들을 기술합니다.
s25.png
[PNG image (177.19 KB)]
메세지박스를 띄우기 위해서는 먼저 메세지박스가 선언되어 있는 헤더파일을 포함해야 합니다. ( qmessagebox.h ) 메세지박스를 사용하는 경우는 스트링을 그대로 출력할경우 인코딩 문제가 발생하므로 QTextCodec객체를 생성해서 utf8로 인코딩해서 출력합니다.


#include < qmessagebox.h >
#include < qtextcodec.h >

void Form_Main::pushButton_hello_clicked()
{

	//local variables :
	QTextCodec* pQTC = NULL;
	QString qstr= "안녕하세요";
		
	pQTC = QTextCodec::codecForName("utf8"); //인코딩할 QTextCodec객체를 생성한다
	if( pQTC == NULL )
	{
		QMessageBox::information( this , this->caption() , "Error!\n" );
		return;
	}
	
	qstr = pQTC->toUnicode(qstr); //utf8로 인코딩한다. 
	QMessageBox::information( this , this->caption() , qstr); //메세지박스를 출력한다 	
	return ;	

}



메세지 박스 출력을 위해서는 Qt Assistance에서 QMessageBox 항목을 확인하시고 인코딩을 위해서는 QTextCodec 클래스를 확인하시기 바랍니다.


radiobuttons


라디오 버튼은 여러 항목중에서 한 가지를 선택해야 하는 상황을 만들 때 효과적으로 사용될 수 있습니다. 여러 라디오 버튼 중에서 한 가지만을 선택하도록 하기 위해서는 QButtonGroup에 여러 라디오 버튼들을 삽입하면 됩니다.

s26.png
[PNG image (195.48 KB)]



그림과 같이 QButtonGroup을 추가하고 QRadioButton도 추가한 후 QRadioButton을 QButtonBroup으로 끌어 포함시킵니다. 라디오버튼이 체크되었는지 확인하기 위해서 QRadioButton의 isChecked() 함수를 사용합니다.


#include < qbuttongroup.h >
#include < qmessagebox.h >
#include < qtextcodec.h >
#include < qradiobutton.h >


void Form_Main::pushButton_hello_clicked()
{
	//local variables :
	QString qstr_Selected = "Nothing Selected";
	
	
	if( this->radioButton_A->isChecked())
	{
		qstr_Selected = radioButton_A->text();
	}
	if( this->radioButton_B->isChecked())
	{
		qstr_Selected = radioButton_B->text();	
	}
	if( this->radioButton_C->isChecked())
	{
		qstr_Selected = radioButton_C->text();	
	}	
	qstr_Selected += "                              "; 
	
	QMessageBox::information( this , this->caption() , qstr_Selected );
	return ;	
}


s27.png
[PNG image (154.65 KB)]


하나의 QButtonGroup에 속한 QRadioButton중 하나만 선택되는 것을 확인합니다.



tabWidget


tabWidget은 일종의 여러 윈도우들이 문서 파일처럼 모여 있는 컨트롤입니다. tabWidget은 여러 컨트롤들을 분류할 때 효과적으로 사용할 수 있습니다. Qt Designer의 Project Overview 들이 tabWidget으로 이루어져 있습니다. tabWidget을 생성하고 동적으로 윈도우에 컨트롤을 추가하도록 하겠습니다.

먼저 tabWidget과 tabWidget의 윈도우들에 버튼을 추가하도록 하겠습니다. toolbox에서 끌어와서 추가하여 만들 수 있습니다.

s28.png
[PNG image (182.57 KB)]



다음과 같이 Signal과 Slot을 설정합니다.

s29.png
[PNG image (88.41 KB)]


slot함수들을 다음과 같이 작성합니다. 동적으로 탭을 추가/삭제하며 탭에 컨트롤을 추가하고 Signal/Slot을 설정합니다.


#include < qbuttongroup.h >
#include < qmessagebox.h >
#include < qtextcodec.h >
#include < qradiobutton.h >
#include < qwidget.h >

void Form_Main::pushButton_addtab_cilcked()
{
	//--------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------
	int index;
	QString qstr = "";
	QTextCodec* pQTC = NULL;
	QWidget* pCurrentTabWidget = NULL;
	QWidget* pChildWidget = NULL;
	QPushButton* pQPushButton = NULL;
	//--------------------------------------------------------------------------------------------------
	
	
	
	//
	//새 윈도우를 생성하고 버튼 컨트롤을 윈도우에 추가한 후 윈도우를 tabWidget에 추가한다.
	//
	
	//한글 출력을 위해 인코딩 객체를 생성한다.
	pQTC = QTextCodec::codecForName("utf8"); 
	
	//현재 선택된 페이지를 얻는다.
	pCurrentTabWidget = tabWidget_fruits->currentPage();
	
	//탭 객체에 추가할 페이지를 생성한다. 
	pChildWidget = new QWidget(this->tabWidget_fruits);
	
	//페이지에 버튼 컨트롤을 생성해서 추가한다.
	pQPushButton = new QPushButton(pChildWidget , ""); //버튼 컨트롤 생성	
	index = tabWidget_fruits->indexOf( pCurrentTabWidget ); //현재 선택된 탭의 인덱스를 얻는다.
	qstr = tabWidget_fruits->label( index ); //선택된 탭의 제목을 얻는다.
	
	pQPushButton->setText( qstr ); //버튼의 텍스트를 그 제목으로 한다.
	
	pQPushButton->setGeometry(10 , 10 , 113 , 26); //버튼의 위치와 크기를 설정한다.
	
	//새로 생성한 버튼에 대해 clicked()시의 핸들러를 설정한다.
	connect( pQPushButton , SIGNAL( clicked() ), this, SLOT( pushButton_insidetab_clicked() ) );
	
	//tabWidget에 새로 생성한 페이지를 추가
	this->tabWidget_fruits->addTab( pChildWidget , qstr );
}


void Form_Main::pushButton_deletetab_clicked()
{
	//--------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------
	QWidget* pQWidget_Current = NULL;
	//--------------------------------------------------------------------------------------------------

	//
	//현재 선택된 탭 페이지를 얻어서 tabWidget에서 삭제한다. 
	//
	
	pQWidget_Current = tabWidget_fruits->currentPage(); //현재 페이지를 얻는다.
	tabWidget_fruits->removePage(pQWidget_Current); //페이지를 tabWidget에서 삭제한다.
	delete pQWidget_Current; //페이지를 지운다.
	pQWidget_Current = NULL;
	return;
}


void Form_Main::pushButton_insidetab_clicked()
{
	//--------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------
	QWidget* pQWidget_Current = NULL;
	QString qstr=""; 
	QTextCodec* pQTC = NULL;
	int index;
	//--------------------------------------------------------------------------------------------------
	
	
	//
	// tabWidget에 추가된 페이지의 버튼의 핸들러. 
         // 현재 페이지의 제목과 탭 인덱스를 메세지박스로 보여준다.
	//
	
	//한글 출력을 위해 인코딩 객체를 생성한다.
	pQTC = QTextCodec::codecForName("utf8"); 
	
	pQWidget_Current = tabWidget_fruits->currentPage(); //현재 페이지를 얻는다.
	if( pQWidget_Current )
	{	
                  //현재 선택된 탭의 인덱스를 얻는다.
		index = tabWidget_fruits->indexOf( pQWidget_Current );		
                  //sprintf함수를 c 표준 스트링 함수와 사용법이 동일하다. 
                  //호출한 QString 객체에 문자열이 저장된다. 
                  qstr.sprintf("탭 인덱스 : %d\n탭 제목 : " , index ); 
		qstr = pQTC->toUnicode( qstr ); //생성한 스트링을 유니코드로 변환
		qstr = qstr + tabWidget_fruits->label( index ) ; 
		QMessageBox::information( this , this->caption() , qstr );	
	}
	else
	{
		QMessageBox::information(this , this->caption() , "nothing selected" );
	}
	
}




탭 인덱스는 0부터 시작합니다.

s210.png
[PNG image (217.16 KB)]




listView


listView 컨트롤은 list/tree view를 표현할 수 있습니다. 여러 행과 열을 트리 구조로 표현합니다. 트리의 각각의 아이템들은 자신과 연관된 다른 아이템들과 부모/자식/형제 관계를 이룹니다.

s211.png
[PNG image (176.11 KB)]



listView는 QListView 클래스의 객체이며, 내부의 아이템들은 QListViewItem클래스의 객체입니다. ToolBox에서 listView컨트롤을 끌어와 설치하거나 코드에서 동적으로 컨트롤을 설정한 후 적당히 column들을 설정하고 아이템을 추가/삭제하는 코드를 작성하면 됩니다.

각각의 아이템을 클릭하면 listView 컨트롤에서 doubleClicked() 이벤트가 발생합니다. 필요하다면 Signal/Slot에서 처리하면 됩니다.

시작시, listView컨트롤의 아이템과 column을 초기화하고 버튼을 클릭하면 아이템을 추가하거나 선택된 아이템을 삭제하는 예제를 작성해 보도록 하겠습니다.


s212.png
[PNG image (156.71 KB)]
트롤 배치



s213.png
[PNG image (94.32 KB)]
Signal/Slot설정



#include < qlistview.h >
#include < qtextcodec.h >
#include < qdatetime.h >
#include < qpixmap.h >
#include < qmessagebox.h >



//--------------------------------------------------------------------------------------------------------------
// constant definitions : 
//--------------------------------------------------------------------------------------------------------------

static const char* folder_closed_xpm[]={
	"16 16 9 1",
	"g c #808080",
	"b c #c0c000",
	"e c #c0c0c0",
	"# c #000000",
	"c c #ffff00",
	". c None",
	"a c #585858",
	"f c #a0a0a4",
	"d c #ffffff",
	"..###...........",
	".#abc##.........",
	".#daabc#####....",
	".#ddeaabbccc#...",
	".#dedeeabbbba...",
	".#edeeeeaaaab#..",
	".#deeeeeeefe#ba.",
	".#eeeeeeefef#ba.",
	".#eeeeeefeff#ba.",
	".#eeeeefefff#ba.",
	".##geefeffff#ba.",
	"...##gefffff#ba.",
	".....##fffff#ba.",
	".......##fff#b##",
	".........##f#b##",
	"...........####."};

static const char* folder_open_xpm[]={
	"16 16 11 1",
	"# c #000000",
	"g c #c0c0c0",
	"e c #303030",
	"a c #ffa858",
	"b c #808080",
	"d c #a0a0a4",
	"f c #585858",
	"c c #ffdca8",
	"h c #dcdcdc",
	"i c #ffffff",
	". c None",
	"....###.........",
	"....#ab##.......",
	"....#acab####...",
	"###.#acccccca#..",
	"#ddefaaaccccca#.",
	"#bdddbaaaacccab#",
	".eddddbbaaaacab#",
	".#bddggdbbaaaab#",
	"..edgdggggbbaab#",
	"..#bgggghghdaab#",
	"...ebhggghicfab#",
	"....#edhhiiidab#",
	"......#egiiicfb#",
	"........#egiibb#",
	"..........#egib#",
	"............#ee#"};

static const char * folder_locked[]={
	"16 16 10 1",
	"h c #808080",
	"b c #ffa858",
	"f c #c0c0c0",
	"e c #c05800",
	"# c #000000",
	"c c #ffdca8",
	". c None",
	"a c #585858",
	"g c #a0a0a4",
	"d c #ffffff",
	"..#a#...........",
	".#abc####.......",
	".#daa#eee#......",
	".#ddf#e##b#.....",
	".#dfd#e#bcb##...",
	".#fdccc#daaab#..",
	".#dfbbbccgfg#ba.",
	".#ffb#ebbfgg#ba.",
	".#ffbbe#bggg#ba.",
	".#fffbbebggg#ba.",
	".##hf#ebbggg#ba.",
	"...###e#gggg#ba.",
	".....#e#gggg#ba.",
	"......###ggg#b##",
	".........##g#b##",
	"...........####."};

static const char * pix_file []={
	"16 16 7 1",
	"# c #000000",
	"b c #ffffff",
	"e c #000000",
	"d c #404000",
	"c c #c0c000",
	"a c #ffffc0",
	". c None",
	"................",
	".........#......",
	"......#.#a##....",
	".....#b#bbba##..",
	"....#b#bbbabbb#.",
	"...#b#bba##bb#..",
	"..#b#abb#bb##...",
	".#a#aab#bbbab##.",
	"#a#aaa#bcbbbbbb#",
	"#ccdc#bcbbcbbb#.",
	".##c#bcbbcabb#..",
	"...#acbacbbbe...",
	"..#aaaacaba#....",
	"...##aaaaa#.....",
	".....##aa#......",
	".......##......."};
//--------------------------------------------------------------------------------------------------------------------------------



//--------------------------------------------------------------------------------------------------------------------------------
//global definitions : 
//--------------------------------------------------------------------------------------------------------------------------------
QPixmap *g_pQPixmap_folderLocked 	= NULL;
QPixmap *g_pQPixmap_folderClosed 	= NULL;
QPixmap *g_pQPixmap_folderOpen 	= NULL;
QPixmap *g_pQPixmap_fileNormal 	= NULL;
//--------------------------------------------------------------------------------------------------------------------------------




//--------------------------------------------------------------------------------------------------------------------------------
// Form_Main::Initialize() :컨트롤들을 초기화.
//--------------------------------------------------------------------------------------------------------------------------------
void Form_Main::Initialize()
{
	
	//--------------------------------------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------------------------------------
	QString qstr;
	QTextCodec* pQTC;		
	//--------------------------------------------------------------------------------------------------------------------------------
	
	
	//
	// 인코딩을 위한 QTextCodec 객체 생성
	//
	
	pQTC = QTextCodec::codecForName("utf8"); 
	
	
	
	//
	// 사용할 아이콘들을 생성한다.
	//
	
	g_pQPixmap_folderLocked	= new QPixmap( folder_locked );
	g_pQPixmap_folderClosed 	= new QPixmap( folder_closed_xpm );
	g_pQPixmap_folderOpen 	= new QPixmap( folder_open_xpm );
	g_pQPixmap_fileNormal 	= new QPixmap( pix_file );
	
	
	//
	//모든 column들을 지운다.
	//
	
	listView1->clear(); //listView의 item을 모두 지운다.	
	//column들을 모두 지운다.
	while( listView1->columns() )
	{
		this->listView1->removeColumn(0);
	}
	
	
	//
	//칼럼들을 추가한다.
	//
	
	qstr = "tree";
	qstr = pQTC->toUnicode( qstr );
	this->listView1->addColumn( qstr );
	
	qstr = "description";
	qstr = pQTC->toUnicode( qstr );
	this->listView1->addColumn( qstr );
}


void Form_Main::pushButton_add_clicked()
{
	
	//--------------------------------------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------------------------------------
	QListViewItem *pParentItem = NULL , *pChildItem = NULL;
	QString qstrs[2];
	QTextCodec* pQTC;
	//--------------------------------------------------------------------------------------------------------------------------------
	
	
	//
	// 인코딩을 위한 QTextCodec 객체 생성
	//
	
	pQTC = QTextCodec::codecForName("utf8"); 
	
	
	//
	// listViewItem생성을 위한 스트링을 만듬
	//
	
	qstrs[0] = "아이템";
	qstrs[0] += (QTime::currentTime()).toString();
	qstrs[1] = (QTime::currentTime()).toString();	
	qstrs[0] = pQTC->toUnicode( qstrs[0] );
	qstrs[1] = pQTC->toUnicode( qstrs[1] );
	
	pParentItem = listView1->selectedItem(); //현재 클릭된 아이템을 선택
	if( pParentItem == NULL )
	{
		//루트의 자식으로 생성
		pChildItem = new QListViewItem( listView1 , qstrs[0] , qstrs[1] );		
		
	}
	else
	{
		//선택된 listViewItem의 자식으로 생성
		pChildItem = new QListViewItem( pParentItem , qstrs[0] , qstrs[1] );
	}
	
	//item의pixmap(아이콘)을 설정
	pChildItem->setPixmap( 0 , *g_pQPixmap_folderLocked );
	pChildItem->setPixmap( 1 , *g_pQPixmap_folderLocked );	
	
	return;
}

void Form_Main::listView1_clicked()
{
	//--------------------------------------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------------------------------------
	QListViewItem *pItem = NULL;
	QPixmap* pPixmap;
	QString qstrs[2];
	QTextCodec* pQTC;
	//--------------------------------------------------------------------------------------------------------------------------------
	
	
	//
	// 선택된 컨트롤이 확장(isOpen()) 되었는지의 여부에 따라 아이콘 이미지를 바꾼다.
	//	
		
	pItem = listView1->selectedItem(); //선택된 아이템에 대한 포인터를 얻는다.	
	if(  pItem->isOpen()  ) //확장된 상태이면 열려있는 이미지로 설정
	{
		pItem->setPixmap( 0 , *g_pQPixmap_folderOpen );
		pItem->setPixmap( 1 , *g_pQPixmap_folderOpen );		
	}
	else //닫힌 상태이면 닫혀있는 이미지로 설정
	{
		pItem->setPixmap( 0 , *g_pQPixmap_folderLocked );
		pItem->setPixmap( 1 , *g_pQPixmap_folderLocked );		
	}
	
	return;
}


void Form_Main::pushButton_delete_clicked()
{
	//--------------------------------------------------------------------------------------------------------------------------------
	//local variables : 
	//--------------------------------------------------------------------------------------------------------------------------------
	QListViewItem *pItem = NULL  , *pParentItem = NULL ;
	//--------------------------------------------------------------------------------------------------------------------------------
	
	pItem = listView1->selectedItem(); //선택된 아이템에 대한 포인터를 얻는다.
	if( pItem != NULL )
	{
		pParentItem = pItem->parent(); //선택된  아이템의 부모 아이템에 대한 포인터를 얻는다.
		if(pParentItem != NULL )
		{
			//부모가 존재한다면 부모에 대한 포인터를 이용하여 takeItem() 함수를 이용하여 삭제하고,
			pParentItem->takeItem( pItem );
			delete pItem;
			pItem = NULL;
		}
		else
		{
			//부모에 대한 포인터가 없으면 가장 높은 단계의 포인터이므로 
			//직접 listView에서 takeItem()을 호출한다.
			listView1->takeItem( pItem );
			delete pItem;
			pItem = NULL;
		}
	}
	else
	{
		return;
	}
	
}




QListView에 아이템을 추가하고 삭제하는 부분을 확인하세요.




#include < qapplication.h >
#include "form_main.h"

int main( int argc, char ** argv )
{
    QApplication a( argc, argv );
    Form_Main w;
    w.Initialize();
    w.show();
    a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
    return a.exec();
}



기존의 코드에서 w.Initialize()함수를 생성 후 호출하여 listView컨트롤을 초기화하는 부분만이 추가되었습니다.




Inputs
s261.png
[PNG image (186.97 KB)]

텍스트,날짜,시간등의 입력을 받는 컨트롤들입니다.

QLineEdit : 한줄 텍스트를 받거나 출력할 때 사용합니다. QTimeEdit : 시간 표현을 받거나 출력할 때 사용합니다. QDateEdit : 날짜 표현을 받거나 출력할 때 사용합니다. QComboBox : 드롭다운 리스트와 펼치기 버튼으로 이루어져 있으며, 여러 항목중 하나를 고를 때 사용합니다.

QLineEdit , QTextEdit 컨트롤은 입력된 텍스트를 text()속성을 이용하여 QString 형식으로 얻거나 설정할 수 있으며 QTimeEdit은 time()속성을 이용하여 QTime객체로,QDateEdit은 date()객체를 이용하여 QDate객체로 얻을 수 있습니다.

아래의 각각의 컨트롤에 대한 간단한 사용예와 Qt Assistance를 보고 참고하시기 바랍니다.

컨트롤 배치
s272.png
[PNG image (240.85 KB)]


s274.png
[PNG image (119.51 KB)]
Signal/Slot설정


위 signal/slot 설정과 각각의 컨트롤에서 값을 얻는 부분을 대조해가면서 확인하세요





#include < qmessagebox.h >

QString g_qstr;

void Form_Main::pushButton_lineEdit_clicked()
{
	g_qstr = lineEdit->text();
	QMessageBox::information(this , this->caption() , g_qstr );
}


void Form_Main::pushButton_dateEdit_clicked()
{
	QDate date;
	date = dateEdit->date();
	QMessageBox::information( this , this->caption() , date.toString() );
}


void Form_Main::pushButton_timeEdit_clicked()
{
	QTime time;
	time = timeEdit->time();
	QMessageBox::information( this , this->caption() , time.toString() );
}


void Form_Main::pushButton_textEdit_clicked()
{
	g_qstr = textEdit->text();
	QMessageBox::information( this , this->caption() , g_qstr );
}


void Form_Main::pushButton_comboBox_clicked()
{
	g_qstr = this->lineEdit_scrollbar->text();
	if( g_qstr.length() > 0 )
	{
		this->comboBox->insertItem( g_qstr );		
	}
}


void Form_Main::scrollbar_sliderMoved()
{
	lineEdit_scrollbar->setText( g_qstr.sprintf("selected scrollbar value : %d" , scrollBar->value() ) );
}





컨트롤들의 종류는 다양하지만, 모두 Qt Assistance에 클래스의 상속구조, 함수, 속성, 정적함수, 예제 코드가 있습니다. 이번 예제들을 참고하면서 Qt Assistance를 검색하고 필요한 정보를 찾는 것에 익숙해졌으면 합니다.



배우면서 작성하는 것이라 잘못된 내용이 있을 수 있습니다. 오류가 있으면, firsttimelove@hotmail.com 으로 알려주시면 빠르게 고치도록 하겠습니다. 좋은 하루 되세요



sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2007-10-28 21:12:10
Processing time 0.0351 sec