Development/Tutorials/Saving and loading (fa)

< Development‎ | Tutorials
Revision as of 16:46, 15 July 2012 by AnneW (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


ذخیره و بازیابی
سری آموزشی   آموزش مقدماتی
پیش‌نیازها   آموزش ۳ - KActionها
پس از این   آموزش ۵ - استفاده از KCmdLineArgs
مطالعه‌ی بیشتر   KIO::NetAccess QFile

Contents

چکیده

حالا یک ویرایشگر متن ساده داریم، ولی هنوز کار به‌دردبخوری انجام نمی‌دهد. یک ویرایشگر متن باید حداقل بتواند فایل‌ها را از دیسک بخواند، فایل‌هایی که شما ساخته یا ویراسته‌اید را ذخیره کند و همین‌طور فایل جدید بسازد.

‏KDE برای کار با فایل‌ها کلاس‌هایی دارد که کار را برای برنامه‌نویسان بسیار آسان می‌سازد. کتاب‌خانه‌ی KIO به شما امکان می‌دهد به سادگی به فایل‌ها دسترسی پیدا کنید. هم‌چنین با کمک KIO می‌توانید از کادرهای استاندارد بازکردن و ذخیره‌سازی فایل‌ها در برنامه‌تان استفاده کنید.

Introtokdetutorial4.png

کدهای منبع

main.cpp

  1. #include <KApplication>
  2. #include <KAboutData>
  3. #include <KCmdLineArgs>
  4.  
  5. #include "mainwindow.h"
  6.  
  7. int main (int argc, char *argv[])
  8. {
  9.   KAboutData aboutData( "tutorial4", "tutorial4",
  10.         ki18n("Tutorial 4"), "1.0",
  11.         ki18n("A simple text area which can load and save."),
  12.         KAboutData::License_GPL,
  13.         ki18n("Copyright (c) 2007 Developer") );
  14.   KCmdLineArgs::init( argc, argv, &aboutData );
  15.   KApplication app;
  16.  
  17.   MainWindow* window = new MainWindow();
  18.  
  19.   window->show();
  20.  
  21.   return app.exec();
  22. }

main.cpp نسبت به آموزش قبل هیچ تغییری نکرده فقط tutorial3ها به tutorial4 تغییر داده‌شده‌اند.

mainwindow.h

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3.  
  4. #include <KXmlGuiWindow>
  5. #include <KTextEdit>
  6.  
  7. class MainWindow : public KXmlGuiWindow
  8.   Q_OBJECT
  9.  
  10. {
  11.   public:
  12.     MainWindow(QWidget *parent=0);
  13.  
  14.   private:
  15.     KTextEdit* textArea;
  16.     void setupActions();
  17. 	QString fileName; //new
  18.  
  19.   private slots:
  20. 	void newFile(); //new
  21. 	void openFile(); //new
  22. 	void saveFile(); //new
  23. 	void saveFileAs(); //new
  24. 	void saveFileAs(const QString &outputFileName); //new
  25. };
  26.  
  27. #endif

از آنجایی که می‌خواهیم قابلیت‌های ذخیره و بازیابی فایل‌ها را به برنامه بیافزاییم، باید توابعی اضافه کنیم که این کارها را برایمان انجام دهند. چون این توابع از طریق مکانیزم signal/slot مربوط به Qt فراخوانی می‌شوند، باید آن‌ها را به عنوان slot معرفی کنیم؛ که در سطر ۱۹ همین اتفاق می‌افتد. به علاوه، چون در این کلاس slot تعریف می‌کنیم، باید ماکروی Q_OBJECT را به تعریف آن اضافه کنیم.

هم‌چنین در طول برنامه، باید نام فایلی که کاربر باز کرده‌است را بدانیم؛ بنابراین متغیر {qt|QString} fileName را اعلان می‌کنیم.

mainwindow.cpp

  1. #include "mainwindow.h"
  2.  
  3. #include <KApplication>
  4. #include <KAction>
  5. #include <KLocale>
  6. #include <KActionCollection>
  7. #include <KStandardAction>
  8. #include <KFileDialog> //new
  9. #include <KMessageBox> //new
  10. #include <KIO/NetAccess> //new
  11. #include <KSaveFile> //new
  12. #include <QTextStream> //new
  13.  
  14. MainWindow::MainWindow(QWidget *parent)
  15.   : KXmlGuiWindow(parent),
  16. 	fileName(QString()) //new
  17. {
  18.   textArea = new KTextEdit;
  19.   setCentralWidget(textArea);
  20.  
  21.   setupActions();
  22. }
  23.  
  24. void MainWindow::setupActions()
  25. {
  26.   KAction* clearAction = new KAction(this);
  27.   clearAction->setText(i18n("Clear"));
  28.   clearAction->setIcon(KIcon("document-new"));
  29.   clearAction->setShortcut(Qt::CTRL + Qt::Key_W);
  30.   actionCollection()->addAction("clear", clearAction);
  31.   connect(clearAction, SIGNAL(triggered(bool)),
  32.           textArea, SLOT(clear()));
  33.  
  34.   KStandardAction::quit(kapp, SLOT(quit()),
  35.                         actionCollection());
  36.  
  37.   KStandardAction::open(this, SLOT(openFile()),
  38.                         actionCollection()); //new
  39.  
  40.   KStandardAction::save(this, SLOT(saveFile()),
  41.                         actionCollection()); //new
  42.  
  43.   KStandardAction::saveAs(this, SLOT(saveFileAs()),
  44. 						actionCollection()); //new
  45.  
  46.   KStandardAction::openNew(this, SLOT(newFile()),
  47. 						actionCollection()); //new
  48.  
  49.   setupGUI();
  50. }
  51.  
  52. //New from here on
  53.  
  54. void MainWindow::newFile()
  55. {
  56. 	fileName.clear();
  57. 	textArea->clear();
  58. }
  59.  
  60. void MainWindow::saveFileAs(const QString &outputFileName)
  61. {
  62. 	KSaveFile file(outputFileName);
  63. 	file.open();
  64.  
  65. 	QByteArray outputByteArray;
  66. 	outputByteArray.append(textArea->toPlainText().toUtf8());
  67. 	file.write(outputByteArray);
  68. 	file.finalize();
  69. 	file.close();
  70.  
  71. 	fileName = outputFileName;
  72. }
  73.  
  74. void MainWindow::saveFileAs()
  75. {
  76. 	saveFileAs(KFileDialog::getSaveFileName());
  77. }
  78.  
  79. void MainWindow::saveFile()
  80. {
  81. 	if(!fileName.isEmpty())
  82. 	{
  83. 		saveFileAs(fileName);
  84. 	}
  85. 	else
  86. 	{
  87. 		saveFileAs();
  88. 	}
  89. }
  90.  
  91. void MainWindow::openFile()
  92. {
  93. 	QString fileNameFromDialog = KFileDialog::getOpenFileName();
  94.  
  95. 	QString tmpFile;
  96. 	if(KIO::NetAccess::download(fileNameFromDialog, tmpFile,
  97. 			this))
  98. 	{
  99. 		QFile file(tmpFile);
  100. 		file.open(QIODevice::ReadOnly);
  101. 		textArea->setPlainText(QTextStream(&file).readAll());
  102. 		fileName = fileNameFromDialog;
  103.  
  104. 		KIO::NetAccess::removeTempFile(tmpFile);
  105. 	}
  106. 	else
  107. 	{
  108. 		KMessageBox::error(this,
  109. 			KIO::NetAccess::lastErrorString());
  110. 	}
  111. }

tutorial4ui.rc

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <gui name="tutorial4"
  3.      version="1"
  4.      xmlns="http://www.kde.org/standards/kxmlgui/1.0"
  5.      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.      xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
  7.                          http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
  8.  
  9.   <MenuBar>
  10.     <Menu name="file" >
  11.       <Action name="clear" />
  12.     </Menu>
  13.   </MenuBar>
  14.  
  15.   <ToolBar name="mainToolBar" >
  16.     <text>Main Toolbar</text>
  17.     <Action name="clear" />
  18.   </ToolBar>
  19.  
  20. </gui>

این فایل هم دقیقا مشابه tutorial3ui.rc از آموزش ۳ است. تنها نام آن را به tutorial4 تغییر داده‌ایم. نیازی به هیچ‌گونه اطلاعات اضافی از KStandardActionها در این فایل نیست. جای هر یک از گزینه‌ها در منوها را به طور خودکار KDE تنظیم می‌کند.

شرح

خوب. پس می‌خواهیم برنامه‌ای بنویسم که ذخیره و بازیابی انجام دهد. این کار در mainwindow.cpp اتفاق می‌افتد.

نخستین کاری که انجام می‌دهیم، اضافه‌کردن

fileName(QString())

به تعریف تابع سازنده‌ی MainWindow در سطر ۱۶ است. با این کار، اطمینان حاصل می‌کنیم که fileName از همان ابتدا تهی است.

افزودن actionها

در اینجا، ارائه‌ی یک رابط بیرونی به کاربران برنامه، اولین کاری خواهد بود که می‌خواهیم انجام دهیم. رابط کاربر برنامه به کاربران اجازه می‌دهد به برنامه بگویند فایل را باز کن، ذخیره کن یا فایل جدیدی بساز. به مانند گزینه‌ی quit در آموزش ۳، از KStandardActionها استفاده می‌کنیم. در طول سطرهای ۳۷ تا ۴۷ actionهای جدید را به منو اضافه می‌کنیم و هر کدام را به slot مناسبی که در فایل سرایند تعریف کرده‌ایم، پیوند می‌دهیم.

ساختن یک فایل جدید

اولین تابعی که می‌نویسیم، تابع newFile() است.

void MainWindow::newFile()
{
  fileName.clear();
  textArea->clear();
}

fileName.clear() مقدار متغیر fileName را تهی قرار می‌دهد. این کار، نمودی از این حقیقت است که فایل هنوز بر روی دیسک وجود ندارد. آن‌گاه textArea->clear() کادر متنی وسط پنجره را خالی می‌کند. این همان تابعی است که به clearAction در آموزش ۳ پیوند زدیم.

ذخیره‌کردن یک فایل

saveFileAs(QString)

حالا می‌خواهیم اولین کدی که با فایل‌ها سر و کار دارد، بنویسیم. می‌خواهیم تابعی پیاده‌سازی کنیم که نوشته‌های درون کادر متن را در یک فایل، با نامی که به عنوان پارامتر رد می‌کنیم، ذخیره کند. KDE کلاسی در اختیار ما می‌گذارد که به کمک آن بتوانیم با اطمینان فایلی را ذخیره کنیم. این کلاس KSaveFile نام دارد و از کلاس QFile متعلق به Qt مشتق شده است.

اعلان تابع به این صورت است:

void MainWindow::saveFileAs(const QString &outputFileName)

سپس شیء KSaveFile خود را می‌سازیم و باز می‌کنیم:

KSaveFile file(outputFileName);
file.open();

حالا که فایلمان باز شده و آماده‌ی نوشتن است، باید نوشته‌های درون کادر متنی را به قالبی درآوریم که بتوان آن را در فایل نوشت. برای این کار، یک QByteArray می‌سازیم و آن را با متن ساده‌ی درون کادر متن پر می‌کنیم:

QByteArray outputByteArray;
outputByteArray.append(textArea->toPlainText().toUtf8());

حالا با استفاده از تابع KSaveFile::write()، آرایه‌ی ساخته شده را در فایل می‌نویسیم. اگر از یک QFile استفاده می‌کردیم، تغییرات بلافاصله در فایل ذخیره می‌شدند. با این کار، اگر در میانه‌ی نوشتن مشکلی پیش بیاید، فایل خراب می‌شود. به همین دلیل، KSaveFile ابتدا در یک فایل موقتی می‌نویسد و سپس هنگامی که KSaveFile::finalize() را صدا می‌زنید، تغییرات در فایل واقعی اعمال می‌شوند.

file.write(outputByteArray);
file.finalize();
file.close();

در پایان، مقدار عضو داده‌ی fileName در کلاس MainWindow را به نام فایلی که نوشته‌ها را در آن ذخیره کردیم، تغییر می‌دهیم.

fileName = outputFileName;

saveFileAs()

این تابعی است که اسلات saveAs به آن پیوند خورده‌است. این تابع تنها تابع عمومی saveFileAs(QString) را با مقدار برگشتی تابع KFileDialog::getSaveFileName() به عنوان آرگومان فرا می‌خواند.

void MainWindow::saveFileAs()
{
  saveFileAs(KFileDialog::getSaveFileName());
}

این اولین استفاده‌ی واقعی ما از کتاب‌خانه‌ی KIO است. KFileDialog تعدادی تابع استاتیک در اختیار ما می‌گذارد تا بتوانیم کادرهای محاوره‌ای عمومی فایل (یعنی همان کادرهای Open/Save File) را نمایش دهیم. با فراخوانی KFileDialog::getSaveFileName()، پنجره‌ای باز می‌شود که از آن‌جا کاربر می‌تواند برای فایل خود نامی برگزیند. تابع نام کامل فایل (همراه با مسیر ذخیره‌سازی) برمی‌گرداند. این مقدار بازگشتی، سپس، به تابع saveFileAs(QString) رد می‌شود.

saveFile()

void MainWindow::saveFile()
{
  if(!fileName.isEmpty())
  {
    saveFileAs(fileName);
  }
  else
  {
    saveFileAs();
  }
}

در این تابع چیز چندان جالب توجهی وجود ندارد؛ فقط منقطی که بر اساس آن تصمیم بگیریم پنجره‌ی ذخیره‌ی فایل را نمایش بدهیم یا نه. اگر fileName خالی نباشد، در این صورت فایل با همان نام fileName ذخیره خواهد شد. در غیر این صورت پنجره‌ی ذخیره‌ی فایل برای کاربر به نمایش در می‌آید تا بتواند نامی انتخاب کند.

بازکردن یک فایل

در پایان، باید به برنامه قابلیت بازیابی فایل‌ها بدهیم. همه‌ی کد این کار در تابع MainWindow::openFile() قرار گرفته است.

اول باید از کاربر بپرسیم نام فایلی که می‌خواهد باز کند چیست. این کار را با استفاده از تابع دیگری از KFileDialog انجام می‌دهیم؛ این بار getOpenFileName():

QString fileNameFromDialog = KFileDialog::getOpenFileName();

حالا از کتاب‌خانه‌ی KIO استفاده می‌کنیم تا فایل را دریافت کنیم. KIO به ما امکان می‌دهد فایل را به صورت یک QFile دریافت کنیم؛ حتی اگر فایل در یک ارتباط راه دور مانند یک FTP قرار داشته باشد. تابع download از NetAccess را به صورت زیر فرا می‌خوانیم:

KIO::NetAccess::download(fileNameFromDialog, tmpFile, this)

اولین آرگومان، نام فایلی است که می‌خواهیم دریافت کنیم. دومی یک متغیر QString است که پس پایان دریافت، مکان کپی موقت فایل را در خود خواهد داشت. از این به بعد با همین tmpFile سر و کار خواهیم داشت.

خروجی تابع، بسته به موفقیت آمیز بودن یا نبودن عملیات، true یا false خواهد بود. اگر عملیات با شکست مواجه شد، پیامی حاوی خطای رخ داده نمایش می‌دهیم:

KMessageBox::error(this, KIO::NetAccess::lastErrorString());

در غیر این صورت، به باز کردن فایل ادامه می‌دهیم.

یک QFile می‌سازیم و فایل موقتی که NetAccess::download() ساخته را به تابع سازنده‌اش رد می‌کنیم. هم‌چنین مشخص می‌کنیم که فایل به صورت «فقط خواندنی» باز شود.

QFile file(tmpFile);
file.open(QIODevice::ReadOnly);

برای نمایش محتویات فایل، باید از یک QTextStream استفاده کنیم. با رد کردن اشاره‌گر file به تابع سازنده‌ی QTextStream یک نمونه می‌سازیم و سپس تابع readAll() آن را فراخوانی می‌کنیم تا نوشته‌ها را از فایل بخوانیم. سپس آن را به تابع setPlainText() مربوط به کادر متنی رد می‌کنیم.

textArea->setPlainText(QTextStream(&file).readAll());

سپس مسیر فایل بازشده را در fileName نگه‌داری می‌کنیم:

fileName = fileNameFromDialog;

و نهایتا فایل موقتی که NetAccess::download() ساخته است را پاک می‌کنیم:

KIO::NetAccess::removeTempFile(tmpFile);

ساخت، نصب و اجرا

CMakeLists.txt

  1. project(tutorial4)
  2.  
  3. find_package(KDE4 REQUIRED)
  4. include_directories(${KDE4_INCLUDES})
  5.  
  6. set(tutorial4_SRCS 
  7.   main.cpp
  8.   mainwindow.cpp
  9. )
  10.  
  11. kde4_add_executable(tutorial4 ${tutorial4_SRCS})
  12.  
  13. target_link_libraries(tutorial4 ${KDE4_KDEUI_LIBS} 
  14.                                 ${KDE4_KIO_LIBS})
  15.  
  16. install(TARGETS tutorial4 DESTINATION ${BIN_INSTALL_DIR})
  17. install(FILES tutorial4ui.rc 
  18.         DESTINATION ${DATA_INSTALL_DIR}/tutorial4)

چون حالا از کتاب‌خانه‌ی KIO استفاده می‌کنیم، باید به CMake بگوییم آن را هم با برنامه‌مان لینک کند. این کار را با رد کردن ${KDE4_KIO_LIBS} به تابع target_link_libraries() انجام می‌دهیم.

با این فایل، می‌توانید برنامه را درست مانند آموزش ۳ بسازید. برای اطلاعات بیشتر، به آموزش ۳ مراجعه کنید.

 mkdir build && cd build
 cmake .. -DCMAKE_INSTALL_PREFIX=$HOME
 make install
 $HOME/bin/tutorial4

به پیش

حالا می‌توانید به سوی آموزش KCmdLineArgs پیش بروید.


This page was last modified on 15 July 2012, at 16:46. This page has been accessed 3,833 times. Content is available under Creative Commons License SA 3.0 as well as the GNU Free Documentation License 1.2.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal