일시 : 2018.11.6

S.시작하며
-개발 세미나 참석은 처음이라 긴장도 되고 외롭기도 했는데.
-ios 개발은 원래 외로운 거더라고요~ 대부분 3명 이하의 조직?에서 개발.. 혼자도 많고
-개발도 잘하고 발표도 잘 하는 분들 많더라!! 이봉원님은 목소리까지 짱!
-계속 공부하고 계속 새로운 것을 봐야 하고 다른 사람들은 뭐하는지 보고 살아야 겠다
-뭔가 소통하고 싶었으나...말 걸...어려웠다ㅠ

-내 기준에서 주목 혹은 기록하고 싶은 것만 정리하면 다음과 같다.
A. iOS 라브 Ruby - 김은영님
ruby로 만들어진 bundler를 이용해서 개발/배포 작업에서 도움이 되는 gem을 사용한다.(사용법은 cocoapod과 동일)
*주목한 gem

1. Houston : local 환경에서 push 테스트할  있는  gem

https://github.com/nomad/houston 

2. Fastlane :  app store 업로드  심사 신청까지 해주는 gem

https://github.com/fastlane/fastlane 

가장 큰 이점은 로컬에서 심사를 위한 업로드로 40분씩  때리지 않아도 된다~


B. RIBs - 김남현님

우버에서 제안하는 크로스 프레임 워크

https://github.com/uber/RIBs/wiki 

모든 Flow를 Tree를 그린다는 관점에서 접근하는 것은 비단 모바일에서만 가능한 일은 아닐 것으로 보인다.


C. GraphQL

REST Api의 단점을 보완하고 HTTP의 특성을 잘 살려낸 API 구현 방식

차세대가 될지는 지켜봐야 하지만 장점이 많은 방식이고 이미 적용된 사례가 생겨나고 있음(GitHub)

https://graphql.org/learn/  


Z.맺으며

경품.

벌킨, 에어팟, 애플와치4!!!!....는 다 남 이야기 ㅠ


by 무위자연 2018. 11. 7. 13:51


just simple


example function : drawFooterArea(QPainter *painter, const QRect& rect, const QSqlRecord& record) const


1 set pen / brush the color you want

painter->setPen(Qt::red);

painter->setBrush(Qt::red);


2. draw Ellipse

painter->drawEllipse(rect);


if you don't set brush, just show circle line


by 무위자연 2018. 9. 27. 10:36


함수 선언을..

void error(char const *msg, bool showKind = true, bool exit);

이런 식으로 하면 다음과 같은 애러가 뜨게 된다.

default argument not at end of parameter list


이것의 의미는 끝에 기본 값을 안 줬다 이며 이것을 해결하기 위해서는

끝에서부터 기본값을 주기 시작해야 한다는 의미이다.

exit도 기본 값을 주던지 아니면 showKind를 제일 뒤로 보내야 한다~


더 자세한 설명은 https://stackoverflow.com/questions/5637679/default-argument-in-the-middle-of-parameter-list 

by 무위자연 2018. 9. 20. 12:29

enum 정의를 해서 사용하는데

그 정의가 늘어날 때마다 관련 코드를 넣는 것은 매우 고통스러운 일이다.

그리고 enum 실제 값과 해당하는 enum을 찾아서 처리해야하는 일들이 생긴다.

그 럴 때 사용하는 것이  QMetaEnum( 관련 문서 : http://doc.qt.io/qt-5/qmetaenum.html )이다.

예제.

class Currency : public QObject
{
Q_OBJECT
public:
enum class CurrencyType
{
    ABC = 1,
    CDE = 2,
    DEF = 3,
   _count,//이것이 있어야 함!!!
}
Q_ENUM(CurrencyType)

QObject를 상속 받아서 정의하고 _count를 넣은 다음에 Q_ENUM으로 정의해주어야 한다.
enum 값을 int로만 사용하면 static_cast<int>를 이용하면 충분하지만 enum의 이름을 사용할 필요가 있을 때 사용한다.

#1 QString to enum
QString 값을 enum value로 바꿔준다.
auto currencyMap = QMetaEnum::fromType<Currency::CurrencyType>(); //enum 클래스를 가지는 객체를 만든다.
QString currency = "ABC";
for (qint32 i = 0; i < currencyMap.keyCount(); i++)
{
    if (currencyMap.key(i) == currency)//key 값과  QString을 비교한다.
   {
                return Currency::CurrencyType(i); 
     }
}


#2 enum to QString

Currency::CurrencyType tempType = currency;

QString currencyString = QVariant::fromValue(currency).value<QString>();


by 무위자연 2018. 9. 11. 10:48


#1 QObject를 상속 받은 tooltip을 처리할 class를 선언한다


at ZenoToolTipHelper.h

class ZenoToolTipHelper : public QObject

{

Q_OBJECT

public:

explicit ZenoToolTipHelper(QObject* parent = NULL)

: QObject(parent)

{

}


protected:

bool eventFilter(QObject* obj, QEvent* event);

};


at ZenoToolTipHelper.cpp

#include <QAbstractItemView>

#include <QToolTip>

#include <QEvent>

#include <QHelpEvent>

bool ZenoToolTipHelper::eventFilter(QObject* obj, QEvent* event)

{

if (event->type() == QEvent::ToolTip)

{

QAbstractItemView* view = qobject_cast<QAbstractItemView*>(obj->parent());

if (view == nullptr)

{

return false;

}


QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);

QPoint pos = helpEvent->pos();

QModelIndex index = view->indexAt(pos);

if (index.isValid() == false)

return false;

//row , column을 적절하게 판단하여서 tooltip을 보여준다.

QFontMetrics fm(view->font());

QRect rect = view->visualRect(index);

int rectWidth = rect.width();


QToolTip::showText(helpEvent->globalPos(),               "tooltip 내용들", view, rect);

return true;


}

return false;

}


#2 #1에서 만들 class를 tableView에 set한다.

tableView->viewport()->installEventFilter(new ZenoToolTipHelper());

by 무위자연 2018. 7. 11. 15:06

QTextEdit에는 setMaxLength 함수가 없다


입력 글자수를 제한하기 위해서 다음과 같이 SLOT을 Connect한다


//member variable

QString tempMemo_ = {};



QTextEdit* memoEdit = dialog_->findChild<QTextEdit*>(toString(ControlID::editMemo));


if (memoEdit->toPlainText().length() > 256)//set maxlength 256

{


disconnect(memoEdit, SIGNAL(textChanged()), this, SLOT(slotValueChanged_memo())));


QTextCursor currentCursor = memoEdit->textCursor();


int pos = currentCursor.position();


memoEdit->setPlainText(tempMemo_);


currentCursor.setPosition(pos - 1, QTextCursor::MoveMode::MoveAnchor);


memoEdit->setTextCursor(currentCursor);


connect(memoEdit, SIGNAL(textChanged()), this, SLOT(slotValueChanged_memo())));


}


else

{

//keep text at last input

tempMemo_ = memoEdit->toPlainText();

}


by 무위자연 2018. 3. 12. 11:16

다음과 같은 요구사항이 있을 경우 상당히 구현하기 까다롭다


requirement : 

YYYY MM DD 로 제한없는 입력보다는 제한된 리스트를 제공하여 콤보박스 형태로 보여줌

단, 직접 입력도 가능하도록 처리

년: 1900~2018 까지 제공
월: 01~12 까지 제공
일: 01~31 까지 제공


이 때 쓸만한 것이 QCompleter


example

QLineEdit으로 text 입력을 받고 여기에 QCompleter를 붙이는 형태이다.

이 때 중요한 것은 model을 설정하는 것. 

1. 파일에서 모델을 읽어오기도 하고 

> 예제  completer->setModel(modelFromFile(":/resources/wordlist.txt")) :: (링크)

2. sql model을 설정하고 특정 컬럼의 데이터만 대상만 보이게 할수도 있다.

> 예제

QSqlQueryModel sample;

completer->setModel(sqmple);

completer->setCompletionColumn(specific column name);

completer->setCompletionMode(QCompleter::PopupCompletion);

3. 하기와 같이 간단하게 string model을 만들수도 있다.


QStringList stringList;

for (int i = 1; i <= selecteddate.daysInMonth(); i++)

{

stringList << QString().sprintf("%02d", i);

}

QStringListModel *dateModel = new QStringListModel(stringList);

QCompleter* dateCompleter = new QCompleter;

dateCompleter->setModel(dateModel);


dateEdit->setCompleter(dateCompleter); //dateEdit은 QLineEdit

by 무위자연 2018. 2. 22. 16:28


해당글은 아이센스라는 회사를 다닌 여정에 대한 글이며 

아웃사이더님의 https://blog.outsider.ne.kr/1339을 보고 영감을 얻었습니다.


Work

2014.5.21~2018.1.12

1. Flex 프로젝트 유지보수 (2014.5~2015.12)

2. MFC 프로젝트 유지보수(VC 6.0, VS2008) (2014.5~)
- 생산 공정 프로그램
- 각종 지원프로그램

3. QT프로젝트 개발(2015.1~)
- 데이터 관리 프로그램
- 생산공정 프로그램
- 각종 지원프로그램

4. 닷넷(WPF)프로젝트 개발(2015.12~)
- 생산공정프로그램
- 병원의 병동 설치 프로그램
- 병원 시스템(EMR, OCS, HIS)과의 Interface 프로그램 
  + 해당 프로그램 개발을 위한 각 병원,업체과의 미팅을 포함한 모든 작업
- 웹서비스 감시 프로그램

5. 웹서비스개발(RubyonRails) (2015.12~) , 설치 및 운용
- DevOps 역할 수행

6. 모바일개발(iOS)
swift - 자사앱 유지보수
objective c - 과제 수행용 앱개발 + watchOS app

개인의 skill set을 고려치 않고 할 수 있는 것은 다 했다
company specific /field specific 정보를 알아간다고해서 안주하지 않으려고 노력했다

나쁜 상황을 헤쳐나가기 위해서 더 스스로를 채찍질하는 시기였다.

혼자 살아남으려고 하지 않고 팀 혹은 내 사람들과 함꼐 성장하려고 노력했다.


Study

업무 이외의 공부를 하는 것이 짧은 호흡이 아니고 꾸준한 내성이 생기기 시작한 시기이다

그 중심엔  과선배이자 스윙고수님이시자 개발자 멘토이신 김대현형 블로그https://medium.com/@hatemogi  - 여기서 공부와 개발에 대한 영감을 얻었다

와 

인프런이  https://www.inflearn.com/  - 이상하게 그 전에 여러 인강 사이트에서 못 느낀 뭔가가 있었다!!! 

누군가가 물어보면 자신있게 최애한다 혹은 인프런에서 배웠어요 라고 말할 수 있다.

있었다.


Blog

15.1.9 구글 애드센스가 승인나면서 본격적으로 사용함 - 

17년도 글 11 개 

16년도 글 29 개 

15년도 글 24 개 

앞으로 일하다가 막혀서 해결한 이력을 남기는 것 이외에 더 많은 내용을 담아볼려고 노력할 예정입니다.

People

힘든 순간에서 가장 힘이 된 것은 역시나 사람 사람 사람입니다.

내가 가장 사랑하는 아내와 2번째 사랑하는 아들

대부님, 앤디형~


늘 영감을 주시는 대현이형~

인프런을 만들어주신 이형주님 그리고 인프런 강의에서 감동을 주신 박순영님

외부 멘토 유부 강태우 - 귀찮을텐데 진짜 도움을 많이 줌 ㅋ 


아쉬운 아이센스 사람들

심승은대리,서민우과장님, 이승천과장님,김진호 대리,한치현대리,박효선대리,류광열차장님,이다연씨


아쉬운 갑 사람들

강원협팀장님, 김기욱차장님, 박태곤대리, 한진영대리, 현유섭씨


그리고 2년간 나의 office wife가 되어준 박무현 과장에게 특히 심심한 감사를 남깁니다.

같이 개발하고 같이 리뷰하고 같이 출장다니고 같이 욕먹고 같이 힘내고

덕분에 나가는 순간까지 아름다울수 있어서 감사하고 고맙고 미안하고


Books

2017>

국가란 무엇인가 0929

야밤의 공대생반화 0829

서버 인프라 엔지니어를 위한 devops 0717

손의 제곱법칙 0531

노무현 운명이다 돌베개 0312

객체 지향의 사실과 오해 0217

2016>
십자군 정쟁 1209

사랑하기 위하여 기도를 배운다 자크필립 10.5

눈먼자들의 국가 5.18

지옥설계도 3.10

대통령의 글쓰기 11.28-1.2


2015>
노인과 바다 어니스트 헤밍웨이 11.27

미친듯이 심플 11.22

마왕신해철 10.31

결국 디자인이다. 9.4

도나 플로르와 그녀의 두 남편 1, 2권  열린책들 from 감정수업 8.,25

욕망을 디자인하다 정경원 8.10

서른에 법구경을 알았더라면 3.18 아버지

화폐전쟁3. 1권 끝 2권 끝3 권 끝

법륜 엄마수업 1.25

2014>

폴오스터 - 선셋파크 12.1

이정명 별을 스치는 바람. 2권 0810

메가쇼킹 더도말고 덜도 말고 쫄깃 0628

여덟단어 5.25

Private

야근 주말 근무 하는 중에도 열심히? 소개팅하고 선보고!!!

연애해서 결혼 하여 아들 출산!

또한 야근 주말 근무 하는 중에도 열심히? 예비자교육 받고 세례성사로 천주인 이 되고 견진성사까지 받음.


Next

더 발전하는 개발자가 될 거 같은 안암역 근처에 있는 회사로 1.25일에 입사합니다. 

이 이야기는 겪어본 다음에 남길게요


by 무위자연 2018. 1. 11. 08:50


  string strUri_get_stripinfos = strUri + DMCMD_get_stripinfos;


            try

            {

                WebRequest wrGETURL;

                wrGETURL = WebRequest.Create(strUri_get_stripinfos);


                Stream objStream;

                objStream = wrGETURL.GetResponse().GetResponseStream();


                StreamReader objReader = new StreamReader(objStream);


                string sLine = "";

                int i = 0;


                while (sLine != null)

                {

                    i++;

                    sLine = objReader.ReadLine();

                    if (sLine != null)

                    {

                        Console.WriteLine("{0}:{1}", i, sLine);

                        if (sLine.Contains("stripinfos") == true)

                        {

                            string response = sLine.Replace("\\", "");

                            response = sLine.Replace("\"", "");

                            response = response.Replace("{", "");

                            response = response.Replace("}", "");

                            response = response.Replace("stripinfos:", "");

                            response = response.Replace("[", "");

                            response = response.Replace("]", "");

                            string[] valuelist = response.Split(',');

                            if (valuelist.Count() > 0)

                            {

                                int selectedindex = -1;

                                List<string> striplist = new List<string>();

                                stripinfolist.Clear();

                                for (int k = 0; k < valuelist.Count(); k++)

                                {

                                    string[] temp = valuelist[k].Split('/');

                                    int tempvalue = 0;

                                    StripInfo info = new StripInfo();

                                    info.lot_number = temp[0];

                                    striplist.Add(temp[0]);

                                    if (temp.Length > 1 && temp[1] == "true")

                                    {

                                        selectedindex = k;

                                        info.aisdefaultatportable = true;

                                    }


                                    if (temp.Length > 2 && int.TryParse(temp[2], out tempvalue) == true)

                                    {

                                        info.min_cs_A_value = tempvalue;

                                    }


                                    if (temp.Length > 3 && int.TryParse(temp[3], out tempvalue) == true)

                                    {

                                        info.max_cs_A_value = tempvalue;

                                    }


                                    if (temp.Length > 4 && int.TryParse(temp[4], out tempvalue) == true)

                                    {

                                        info.min_cs_B_value = tempvalue;

                                    }


                                    if (temp.Length > 5 && int.TryParse(temp[5], out tempvalue) == true)

                                    {

                                        info.max_cs_B_value = tempvalue;

                                    }


                                    stripinfolist.Add(info);                                    

                                }                               


                                stripinfocombobox.IsEnabled = true;

                                stripinfocombobox.ItemsSource = striplist;

                                stripinfocombobox.SelectedIndex = selectedindex;

                                break;

                            }

                            else

                            {

                                

                            }

                        }

                    }

                }


            }

            catch (Exception err)

            {

                string error_msg = "서버에 접속하지 못했거나 해당 기능이 서버에 반영되지 않았습니다. \r\n접속 주소는 " + strUri_get_stripinfos + " 입니다\r\n메세지 :: " + err.Message;

                LogManager.Log(3, error_msg);

                stripinfocombobox.ItemsSource = null;

                stripinfocombobox.IsEnabled = false;

            }

by 무위자연 2018. 1. 10. 17:12

1 include header file

#include <QTcpSocket>

  #include <qabstractsocket.h>


2. declare a variable

QTcpSocket *tcpClient = Q_NULLPTR;


3 connect slot

connect(tcpClient, SIGNAL(connected()), this, SLOT(connectedToDM()));//check connected server

connect(tcpClient, SIGNAL(readyRead()), this, SLOT(ReceiveServerData())); //receive data from server

connect(tcpClient, SIGNAL(disconnected()), this, SLOT(disconnectedfromDM())); //receive signal when disconnected

connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));//// check socket error from server


4. try to connect to server

tcpClient->connectToHost(m_dm_ip, 8000);


5. try to disconnect from server

tcpClient->disconnectFromHost();


6. send message to server

qint64 result = tcpClient->write(data.constData());


7. receive data from server

void MainWindow::ReceiveServerData()

{   

QByteArray servermsg = tcpClient->readAll();    

    QString msg = QString::fromUtf8(servermsg.constData());

 }



8. control socket error

void MainWindow::displayError(QAbstractSocket::SocketError socketError)

{

    Log();

    if (socketError == QTcpSocket::RemoteHostClosedError)

        return;

by 무위자연 2017. 12. 19. 09:50