क्यूटी के लिए ओआरएम का अवलोकन

परिचय



शुभ दोपहर, प्रिय साथी प्रोग्रामर!

अब एक साल के लिए, क्यूटी दुनिया में बहुत दिलचस्प घटनाएं हो रही हैं। यहां आपके पास संस्करण 4.7 की हालिया रिलीज़, क्यूएमएल की अवधारणा और मोबाइल प्लेटफार्मों में पुस्तकालय का महत्वपूर्ण एकीकरण है। क्यूटी में सबसे सही ट्रॉल्स हैं; मुझे पसंद है कि वे क्या करते हैं और यह पुस्तकालय कहां विकसित होता है। मैंने यह भी शर्त लगाई कि वह अपनी कक्षा में सर्वश्रेष्ठ है, लेकिन जो लोग क्यूटी पर लिखते हैं वे पहले से ही यह जानते हैं।

कुछ और है जो वार्षिक अवधि में बदल गया है। क्यूटी के लिए, ओआरएम पुस्तकालय दिखाई देने लगे, एक के बाद एक, मशरूम की तरह। क्या कोई पवित्र स्थान खाली है? एक मांग है, यहां की पेशकश है। इस लेख में Qt ORM दुनिया में क्या हो रहा है पढ़ें। मैं मॉनिटर किए गए पुस्तकालयों में उपयोग और तंत्र पर अधिकतम जानकारी देने का प्रयास करूंगा; लेकिन उनमें से एक को पूरी तरह से इस कारण से स्वीकार नहीं किया जा सकता है कि कोई भी ओआरएम प्रोग्रामिंग समाधान का एक बहुत ही जटिल समूह है।

(मैं तुरंत ध्यान देता हूं कि लेख कुछ हद तक विज्ञापन के लिए है, क्योंकि यह मेरे अपने ओआरएम के कारण प्रकट हुआ; हालांकि, निष्पक्षता में, मैं न केवल खुद को पीआर करता हूं, बल्कि इस विषय पर एक सामान्य मूल्यांकन भी देता हूं कि कृपया समझें: बेहतरीन इरादे)।


QxOrm, वर्। 1.1.1



लेखक / मालिक : QxOrm फ्रांस
साइटें : आधिकारिक , SourceForge पर
लाइसेंस : GPLv3 + वाणिज्यिक
निर्भरताएँ : Qt (4.5+), बढ़ावा (1.38+)
विकास की अवधि : 2010 की शुरुआत, आखिरी बदलाव अप्रैल 2010 है
प्रलेखन : अधूरा, फ्रेंच में
उदाहरण : हाँ, सबसे बुनियादी

विकास का मुख्य लक्ष्य दृढ़ता (QtSql के माध्यम से), क्रमांकन (बढ़ावा के माध्यम से :: क्रमांकन) और प्रतिबिंब प्रदान करना है।

पुस्तकालय बहुत मजबूत दिखता है और बहुत सारी चीजें करने में सक्षम लगता है। डीएओ ( डेटा एक्सेस ऑब्जेक्ट ) के सिद्धांत पर निर्मित, जब एक तालिका में एक पंक्ति प्रदर्शित करने वाला एक वर्ग होता है, और कुछ विधियों का उपयोग करते हुए, डेटाबेस से ऐसी पंक्तियों की एक सूची पुनर्प्राप्त की जाती है। इसे संभव बनाने के लिए, QxOrm बहुत मुश्किल तंत्र का उपयोग करता है, जिसमें टेम्पलेट (बहुत सारे टेम्पलेट), मैक्रोज़, वंशानुक्रम सरल और एकाधिक शामिल हैं। कोड परिचित के लिए बहुत दिलचस्प है, अगर आप प्रोग्रामिंग ट्रिक्स के प्रेमी हैं या, उदाहरण के लिए, आपको अलेक्जेंड्रेस्कु पसंद है।

उदाहरण, कोड और विवरणों को देखते हुए, निम्नलिखित विशेषताएं कार्यान्वित की जाती हैं।

पेशेवरों:

विपक्ष:

विरोधाभासी रूप से, सभी नुकसानों के साथ, QxOrm लगभग पूर्ण-पूर्ण ORM समाधान है जो Qt के साथ संगत है। और यह एकमात्र समाधान है जहां कैशिंग है, जो जटिल परियोजनाओं के लिए महत्वपूर्ण है। आप देखेंगे कि यह छोटी समीक्षा अभी भी दूसरों की तुलना में अधिक है, क्योंकि अन्य ओआरएम की तुलना QxOrm से करने की संभावना नहीं है। हालाँकि, किसी बड़े प्रोजेक्ट में लाइब्रेरी का उपयोग करने पर, आप कुछ अन्य संभावनाएँ प्राप्त कर सकते हैं, खासकर यदि आप एक अमूर्त भंडारण के साथ काम नहीं कर रहे हैं, लेकिन एक पूर्ण DBMS के साथ - लेकिन यह नहीं होगा। आप किसी प्रकार की बग को ठीक करना चाहेंगे - लेकिन यह इतना सरल नहीं है। आपको बहुत सारी साइकिल और बैसाखी का आविष्कार करना होगा। परियोजना अनिवार्य रूप से एक चिमेरा में बदल जाएगी। इसके विपरीत, एक छोटी परियोजना के लिए जहां आपको केवल कुछ अच्छी विशेषताओं की आवश्यकता होती है, पुस्तकालय उपयोगी हो सकता है - इस हद तक कि आप बूस्ट को भी कसने से डरते नहीं हैं।

मैपर क्लास का एक उदाहरण (सभी कोड प्रलेखन से लिया गया है):

क्लास ड्रग
{
जनता :
लंबी आईडी ;
QString नाम ;
QString विवरण ;

दवा ( ) : आईडी ( 0 ) { ; }
आभासी ~ दवा ( ) { ; }
} ;

QX_REGISTER_HPP_MY_TEST_EXE ( दवा, qx :: लक्षण :: no_base_class_defined , 1 )


QX_REGISTER_CPP_MY_TEST_EXE ( दवा ) // यह मैक्रो QxOrm संदर्भ में 'दवा' वर्ग को पंजीकृत करने के लिए आवश्यक है

नामस्थान qx {
टेम्पलेट <> शून्य रजिस्टर_क्लास ( QxClass < दवा > और टी )
{
टी। आईडी ( और दवा :: आईडी , "आईडी" ) ; // रजिस्टर 'दवा :: आईडी' <=> अपने डेटाबेस में प्राथमिक कुंजी
टी। डेटा ( और दवा :: नाम , "नाम" , 1 ) ; // रजिस्टर 'दवा :: नाम' संपत्ति 'कुंजी' नाम और संस्करण '1' के साथ
टी। डेटा ( और दवा :: विवरण , "desc" ) ; // रजिस्टर 'दवा :: विवरण' कुंजी के साथ संपत्ति 'desc'
} }


उपयोग उदाहरण:

// ड्रग्स स्टोर करने के लिए डेटाबेस में टेबल 'ड्रग' बनाएं
QSqlError daoError = qx :: dao :: create_table < drug > ( ) ;

// कंटेनर से डेटाबेस में ड्रग्स डालें
// 'd' की संपत्ति 'd1', 'd2' और 'd3' ऑटो अपडेटेड हैं
daoError = qx :: dao :: insert ( lst_drug ) ;

// डेटाबेस में दूसरी दवा को संशोधित और अपडेट करें
d2 - > नाम = "name2 संशोधित" ;
d2 - > विवरण = "desc2 संशोधित" ;
daoError = qx :: dao :: update ( d2 ) ;

// डेटाबेस से पहली दवा को हटा दें
daoError = qx :: dao :: delete_by_id ( d1 ) ;

// डेटाबेस में दवाओं की गणना
लंबी lDrugCount = qx :: dao :: count < drug > ( ) ;

// एक नए चर में आईडी '3' के साथ दवा प्राप्त करें
drug_ptr d_tmp ; d_tmp। रीसेट ( नई दवा ( ) ) ;
d_tmp - > id = 3 ;
daoError = qx :: dao :: fetch_by_id ( d_tmp ) ;

// एक्सएमएल प्रारूप (क्रमांकन) के तहत एक फ़ाइल से कंटेनर से दवाओं का निर्यात करें
qx :: क्रमांकन :: xml :: to_file ( lst_drug, "/export_drugs.xml " ) ;

// xml फ़ाइल से दवाओं को एक नए कंटेनर में आयात करें
type_lst_drug lst_drug_tmp ;
qx :: serialization :: xml :: from_file ( lst_drug_tmp, "./export_drugs.xml" ) ;

// एक दवा का क्लोन
drug_ptr d_clone = qx :: क्लोन ( * d1 ) ;

// वर्ग नाम (कारखाना) द्वारा एक नई दवा बनाएँ
बढ़ावा देना :: किसी भी d_any = qx :: बनाना ( "दवा" ) ;

// ड्रग्स कंटेनर को 'qx :: cache' में डालें
qx :: cache :: set ( "ड्रग्स" , lst_drug ) ;



QDjango, क्रिया। ???


द्वारा पोस्ट किया गया : जेरेमी Lainé, Bolloré दूरसंचार
साइटें : आधिकारिक , मेलिंग सूची
लाइसेंस : GPLv3, LGPLv3
निर्भरताएँ : Qt (4.5+)
3 जून, 2010 से विकास में
प्रलेखन : पूर्ण, अंग्रेजी में, डॉक्सीजन-जनित
उदाहरण : हाँ, सबसे बुनियादी।

मुख्य लक्ष्य : क्यूटी के लिए एक मुफ्त ओआरएम बनाना, जितना संभव हो उतना Django के समान।

इस विकास के फायदे और नुकसान के बारे में बात करना जल्दबाजी होगी, लाइब्रेरी अभी भी नहीं जानता कि कैसे। जाहिर है, यह एक डीएओ / सक्रिय रिकॉर्ड-ओआरएम होगा। अब पहले से ही SELECT जनरेट करना संभव है, डेटा को एक कंटेनर में पुनः प्राप्त करें, क्रिएट टेबल जेनरेशन के माध्यम से टेबल बनाएं। लेखक ने तुरंत WHERE पीढ़ी को लिखना शुरू किया; इसके अलावा, AND और OR ऑपरेटर समर्थित हैं। यही है, आप एक बहु-स्तरीय फ़िल्टर बना सकते हैं, और फ़िल्टर सेट करने के लिए सिंटैक्स भी सफल होता है। विकास में, समान तरीकों को सक्रिय रूप से QxOrm में उपयोग किया जाता है: टेम्प्लेट, विरासत ... उनके आधार पर, संभवतः, लेखक अच्छे ओओपी कोड के विशाल फार्म बनाने जा रहा है।
लेकिन वह सब है। हम यह मानेंगे कि एक वर्ष में एक आधा शक्तिशाली ORM प्रणाली QDjango से विकसित होगी, लेकिन अभी के लिए, परियोजनाओं में इसके आवेदन के बारे में बात करने की कोई आवश्यकता नहीं है।

लेखक से लिया गया उपयोग का एक उदाहरण।

// सभी उपयोगकर्ता
QDjangoQuerySet < उपयोगकर्ता > उपयोगकर्ता ;

// ऐसे सभी उपयोगकर्ताओं को खोजें जिनका पासवर्ड "foo" है और जिनका उपयोगकर्ता नाम "बार" नहीं है
QDjangoQuerySet < User > someUsers ;
कुछ यूजर्स = उपयोगकर्ता। फ़िल्टर ( QDjangoWhere ( "पासवर्ड" , QDjangoWhere :: बराबर , "फू" ) &&
QDjangoWhere ( "उपयोगकर्ता नाम" , QDjangoWhere :: NotEquals , "bar" ) ) ;

// उन सभी उपयोगकर्ताओं को खोजें जिनके उपयोगकर्ता नाम "फू" या "बार" हैं
कुछ यूजर्स = उपयोगकर्ता। फ़िल्टर ( QDjangoWhere ( "उपयोगकर्ता नाम" , QDjangoWhere :: बराबर , "फू" )) ||
QDjangoWhere ( "उपयोगकर्ता नाम" , QDjangoWhere :: बराबर , "बार" ) ) ;

// उन सभी उपयोगकर्ताओं को खोजें जिनके उपयोगकर्ता नाम "f" से शुरू होते हैं:
कुछ यूजर्स = उपयोगकर्ता। फ़िल्टर ( QDjangoWhere ( "उपयोगकर्ता नाम" , QDjangoWhere :: StartsWith , "f" ) ) ;

// परिणामों की सीमा
कुछ यूजर्स = उपयोगकर्ता। सीमा ( 0 , 100 ) ;

// मिलान करने वाले उपयोगकर्ताओं की संख्या प्राप्त करें
int numberOfUsers = someUsers। आकार ( ) ;

// पहले मिलान वाले उपयोगकर्ता को पुनः प्राप्त करें
उपयोगकर्ता * FirstUser = someUser। पर ( 0 ) ;

// मुफ्त मेमोरी
पहले हटाएं ;

// मिलान करने वाले उपयोगकर्ताओं के लिए उपयोगकर्ता नाम और पासवर्ड की सूची पुनः प्राप्त करें
QList < QList < QVariant >> propertyLists = someUsers। मान सूची ( QStringList ( ) << "उपयोगकर्ता नाम" << "पासवर्ड" ) ;

// क्वेरीसेट में सभी उपयोगकर्ताओं को हटा दें
someUsers। निकालें ( ) ;

उपयोगकर्ता वर्ग:

वर्ग उपयोगकर्ता : सार्वजनिक QDjangoModel
{
Q_OBJECT
Q_PROPERTY ( QString उपयोगकर्ता नाम READ प्रयोक्तानाम WRITE setUsername )
Q_PROPERTY ( QString पासवर्ड पढ़ें पासवर्ड राइट सेटपासवर्ड )

Q_CLASSINFO ( "उपयोगकर्ता नाम" , " max_length = 255" )
Q_CLASSINFO ( "पासवर्ड" , " max_length = 128" )

जनता :
QString उपयोगकर्ता नाम ( ) कास्ट ;
void setUsername ( const QString & username ) ;

QString पासवर्ड ( ) कास्ट ;
शून्य सेटपासवर्ड ( const QString और पासवर्ड ) ;

निजी :
QString m_username ;
QString m_password ;
} ;


QtPersistence, वर्। 0.1.1


द्वारा पोस्ट : मैट रोजर्स
साइटें : SourceForge पर
लाइसेंस : LGPLv3
निर्भरताएँ : Qt (4.5+)
विकास की अवधि : 2009 का अंत - 2010 की शुरुआत
प्रलेखन : कोई नहीं
उदाहरण : यूनिट परीक्षणों में खराब

मुख्य लक्ष्य : रूबी के लिए कुछ (?) के समान सक्रिय रिकॉर्ड दृष्टिकोण के आधार पर क्यूटी के लिए एक ओआरएम बनाएं।

एक और पुस्तकालय जो लगभग कुछ भी नहीं जानता है। क्या बदतर है: और विकसित नहीं होता है; ऐसा लगता है कि लेखक ने इस परियोजना को छोड़ दिया। वास्तव में, वह जो कुछ कर सकती है, वह डेटाबेस पर डेटा लिखने के लिए मैपर क्लास का उपयोग करती है।

उपयोग के एकमात्र उदाहरण यूनिट परीक्षणों (स्व-लिखित परीक्षण मॉड्यूल के आधार पर) में पाए जाते हैं।

क्लास फेकबुक : सार्वजनिक QPersistantObject
{
Q_OBJECT
Q_PROPERTY ( QString लेखक READ लेखक WRITE setAuthor )
Q_PROPERTY ( int yearPublished READ वर्षप्रकाशित WRITE setYearPublished )
जनता :
Q_INVOKABLE फ़ेकबुक ( QObject * पैरेंट = 0 ) : QPersistantObject ( पैरेंट ) { }
वर्चुअल ~ फ़ेकबुक ( ) { }

void setAuthor ( const QString & a ) { m_author = a ; }
QString लेखक ( ) const { वापसी m_author ; }

void setYearPublished ( int वर्ष ) { m_yearPublished = year ; }
int वर्षप्रकाशित ( ) const { वापसी m_yearPublished ; }

निजी :
QString m_author ;
int m_yearPublished ;
} ;

फेकबुक * बी = नया फेकबुक ;
बी - > सेटअथोर ( "मैट रोजर्स" ) ;
b - > setYearPublished ( 2009 ) ;

bool objectSaved = b - > save ( ) ;
हटाना b ;
ASSERT_TRUE ( आपत्तिजनक ) ;

b = नया फेकबुक ;
बी - > सेटऑथोर ( "नॉट मैट रोजर्स" ) ;
b - > setYearPublished ( 1999 ) ;

objectSaved = b - > save ( ) ;
हटाना b ;
ASSERT_TRUE ( आपत्तिजनक ) ;


QsT SQL टूल्स (QST), वर्। 0.4.2a रिलीज़


द्वारा पोस्ट : अलेक्जेंडर Granin (मुझे :))
साइटें : SourceForge , मंच पर
लाइसेंस : GPLv3, LGPLv3
निर्भरताएँ : Qt (4.5+)
सितंबर 2009 से विकास में
दस्तावेज़ीकरण : पूर्ण, डॉक्सीजन-जनित, केवल रूसी में
उदाहरण : इकाई परीक्षणों में, कोड में हैं; मैंने संस्करण 0.3 और 0.4 - पूर्ण-डेटाबेस डेटाबेस अनुप्रयोगों के लिए विशेष TradeDB नमूना परियोजनाएं भी बनाईं।

मुख्य लक्ष्य Qt के तहत डेटाबेस अनुप्रयोगों की प्रोग्रामिंग को सुविधाजनक बनाना है।

अपने ORM के बारे में बात करना आसान नहीं है। यह उसके लिए धन्यवाद था कि मुझे हब्बर मिला, सैंडबॉक्स में एक लेख लिख रहा था। लेख में रुचि नहीं थी ... लेकिन यह संस्करण 0.3 था - और रिलीज भी नहीं, लेकिन पूर्व-अल्फ़ा। अब मैं QST के विकास में बहुत आगे निकल चुका हूं, और 0.5.1 प्री-अल्फा पहले से ही उपलब्ध है; लेकिन फिर भी बहुत कुछ करना बाकी है।

सबसे पहले: यह एक साधारण ओआरएम नहीं है। मैंने लाइब्रेरी लिखना शुरू किया, अभी तक शब्द नहीं जानता; मुझे उन्हें न लिखने के लिए प्रश्नों को उत्पन्न करने के लिए एक उपकरण की आवश्यकता थी, और इसलिए कि वे एक परत में केंद्रित थे: उन पर नज़र रखना आसान था। मुझे एक्टिव रिकॉर्ड जैसे दृष्टिकोणों के बारे में नहीं पता था। परिणाम वही होता है: एक विशिष्ट ORM, जो कि वास्तव में ORM नहीं है। आप इसमें वर्ग फ़ील्ड कॉन्फ़िगर नहीं कर सकते हैं जो तालिका फ़ील्ड में मैप करेगा; केवल असाइनमेंट का उपयोग करके डेटाबेस को (से) सीधे डेटा (पढ़ना) लिखना असंभव है। लेकिन आप कई अन्य चीजें कर सकते हैं।

अवसर, वे पुस्तकालय के फायदे भी हैं।

विपक्ष? बेशक, और बहुत सारे हैं!


सामान्य तौर पर, पुस्तकालय अभी भी विकास में है, लेकिन पहले से ही बहुत सारी चीजें जानता है। मैं इसे अपने काम में उपयोग करता हूं; और एक फ्रीलांसर के रूप में मैं इस पर एक और परियोजना लिख ​​रहा हूं। सामान्य तौर पर, प्रोग्रामर के पास QxOrm या QDjango के साथ की तुलना में बहुत कम काम होता है, जैसा कि उदाहरणों के लिए स्रोत कोड से देखा जा सकता है। वर्णित हैंडलर, उनमें भरा हुआ दृश्य - ऐसी सुविधाएँ प्राप्त करें जो लगभग सभी मुख्य वर्ग (QstAbstractModelHandler) में स्थित हैं। मैं धीरे-धीरे जरूरी सभी चीजों का परिचय देता हूं, लेकिन आप हमेशा मेरी ओर मुड़ सकते हैं, मैं निश्चित रूप से मदद करूंगा। के विपरीत है। इसलिए, मैं इस मुश्किल उपक्रम में मेरा समर्थन करने का प्रस्ताव देता हूं। हालांकि शुभकामनाओं की भी इच्छा; और बेहतर - किसी भी समीक्षा। मैं आभारी रहूंगा।

एक हैंडलर क्लास का उदाहरण और एक सेलेक्ट क्वेरी के लिए DFD डिस्क्रिप्टर।

कृपया ध्यान दें कि QstField फ़ील्ड कस्टमाइज़िंग व्यू के लिए जानकारी भी प्रेषित करते हैं: फ़ील्ड डिस्प्लेबिलिटी, शीर्षक और कॉलम चौड़ाई।
// personhandler.h
const int PERSONS = 1 ;
const int PERSONS_FULL_NAME = 2 ;

वर्ग PersonsHandler : सार्वजनिक QstAbstractModelHandler
{
निजी :

QstBatch _selector ( const int & queryNumber ) कास्ट ;
QstBatch _executor ( const int & queryNumber ) कास्ट ;
} ;

// personhandler.cpp
QstBatch PersonsHandler :: _selector ( const int & queryNumber ) कास्ट
{
QstBatch बैच ;

यदि ( क्वेरीनंबर == व्यक्ति )
{
बैच। addSource ( "vPersons" ) ;
बैच << QstField ( भूमिकाप्रणाली, "आईडी" )
<< QstField ( "पता_आईडी" )

<< QstField ( " लास्टनेम " , फील्डविजय, "लास्ट नेम" , 100 )
<< QstField ( "FirstName" , FieldV अदृश्य, "नाम" , 100 )
<< QstField ( "ParentName" , FieldV अदृश्य, "मध्य नाम " , 100 )
<< QstField ( "vcBirthDate" , FieldV अदृश्य, "दिनांक \ n जन्म" , 90 )
<< QstField ( "फोन" , फील्डविजय, "संपर्क \ n फोन" , 120 )
<< QstField ( "[ई-मेल]" , फील्डविशेष, "ई-मेल" , 120 )

<< QstField ( "ID" , मान ( ID_VALUE ) , उद्देश्य )
;
}
अन्यथा
अगर ( क्वेरीनंबर == PERSONS_FULL_NAME )
{
बैच। addSource ( "vPersons" ) ;
जत्था

<< QstField ( " FullName " , FieldV अदृश्य, "पूर्ण नाम" , 300 )
<< QstField ( " लास्टनेम " , फील्डविजय, "लास्ट नेम" , 100 )
<< QstField ( "FirstName" , FieldV अदृश्य, "नाम" , 100 )
<< QstField ( "ParentName" , FieldV अदृश्य, "मध्य नाम " , 100 )
<< QstField ( "vcBirthDate" , FieldV अदृश्य, "दिनांक \ n जन्म" , 90 )
<< QstField ( "फोन" , फील्डविजय, "संपर्क \ n फोन" , 120 )
<< QstField ( "[ई-मेल]" , फील्डविशेष, "ई-मेल" , 120 )

<< QstField ( "ID" , मान ( ID_VALUE ) , उद्देश्य )


<< QstField ( भूमिकाप्रणाली, "आईडी" )
<< QstField ( "पता_आईडी" )
;
}
अन्यथा
{
Q_ASSERT ( झूठा ) ;
}

वापसी बैच ;
}

अनुकूलन देखें:

// PersonsHandler _personsHandler;
// QstPlainQueryModel _personsModel; // - PersonsForm वर्ग में वर्णित है।

शून्य PersonsForm :: loadPersons ( )
{
_personsHandler। पुनः लोड करें ( PERSONS, & _personsModel ) ;
_personsHandler। setTableView ( ui - > tv_PersonsTableView ) ;
}

QVariant PersonsForm :: personID ( ) कांस्टेबल
{
वापसी _personsHandler। keyValueOfView ( ) ;
}

का उपयोग करें:

शून्य PersonsForm :: loadPersonalDocumentInfo ( )
{
PersonalDocumentsHandler वें ;
वें। setValue ( "Person_ID" , personID ( ) ) ;
QVariantMap valMap = वें। SelectToMap ( PERSONAL_DOCUMENTS,
QStringList ( )
<< "DocTypeName"
<< "SerialNumber"
<< "संख्या"
<< "vcIssueDate"
<< "दिया गया है" ) ;
ui - > le_DocumentTypeLineEdit - > setText ( valMap [ "DocTypeName" ] .String ( ) ) ;
ui - > le_SerialNumberLineEdit - > setText ( valMap [ " Serialumberumber " ]] toString ( ) ;
ui - > le_NumberLineEdit - > setText ( valMap [ "संख्या" ]toString ( ) ) ;
ui - > le_IssueDateDateEdit - > setDate ( valMap [ "vcIssueDate" ]] toDate ( ) ;
ui - > le_GivenByLineEdit - > setText ( valMap [ "दिया गया है" ] .String ( ) ) ;
}

Source: https://habr.com/ru/post/In105191/


All Articles