بتـــــاريخ : 2/26/2011 1:09:15 AM
الفــــــــئة
  • الحـــــــــــاسب
  • التعليقات المشاهدات التقييمات
    0 1236 0

    موضوعات متعلقة

    MCAD &MCSD book

    Qtexteditor SIMPLE SDI Application

    الناقل : elmasry | العمر :42 | الكاتب الأصلى : ahmed_youssef | المصدر : www.arabteam2000-forum.com

    كلمات مفتاحية  :
    Qtexteditor SIMPLE SDI Application

    SDI Application
    Posted Image


    لاحظ إن ال Application عبارة عن
    1 – Main Window
    2 – MenuBar بتشمل File, Edit, Help menus
    3- ToolBar 2
    الأول هو fileToolBar وفيه new, open and save
    التانى هو editToolBar وفيه cut, copy and paste

    4- TextEdit
    5- StatusBar


    هنحتاج نعمل 3 ملفات لل Application
    1- mainwindow.h فيه ال class design
    2- mainwindow.cpp فيه ال class implementation
    3- main.cpp فيه ال entry point لل Application

    mainwindow.h

    بداية قبل اى شئ

    #ifndef MAINWINDOW_H
     #define MAINWINDOW_H

    هنحتاج نعمل include ل QMainWindow
    #include <QMainWindow>
    عشان نورثها لل mainwindow class
    class MainWindow : public QMainWindow


    لاحظ إننا زى ماقلنا هنستخدم menu, toolbar, actions
    class QAction;
     class QMenu;
     class QTextEdit;


    ملحوظة ال actions هى العناصر اللى بتكون ال menus وال toolbars !

    هنعمل فى ال class دا Override لل virtual closeEvent method وهى method بت fired كل ميحصل محاولة ل قفل ال window فإحنا هنعمل ليها new definition عشان نستخدم ال
    famous message “you wanna quit !? “

    ال class هيكون ليه slots خاصة فيه يبقة لازم نعرف الmacro Q_OBJECT!

    ال slots هتكون إيه ؟
    newFile, save, saveAs, about, documentWasModified
    ال newFile هنستخدمها عشان نبدأ فى new file
    ال save/save as عشان نحفظ الملف بيهم
    ال about هنستخدمها عشان نظهر window بتتكلم عن البرنامج وهناك هنستخدم qtabout الموجودة فى Qapplication!
    ال documentWasModified عشان تشير هل الملف اتعدل فيه ولا لأ عشان نستخدم save or not MSG

    ندخل فى ميثودز ال class نفسها بقة

    1- init()
    2- createActions()
    3- createMenus()
    4- createToolBars()
    5- createStatusBar()
    6- bool maybeSave()
    7- loadFile()
    8- bool saveFile()
    9- setCurrentFile()
    10- QString strippedName()
    11- QMainWindow findMainWindow()

    احنا ممكن نخلى ال GUI فى ال Constructor بس المشكلة الوحيدة هى إننا عندنا 2 Constructors فمش عايزين نكرر نفسنا فنعمل ميثود لل init window
    strippedName بترجع لينا اسم الفيل بدون ال full name


    ال fields
    QTextEdit *textEdit;
             QString curFile;
             bool isUntitled;
             QMenu *fileMenu;
             QMenu *editMenu;
             QMenu *helpMenu;
             QToolBar *fileToolBar;
             QToolBar *editToolBar;
             QAction *newAct;
             QAction *openAct;
             QAction *saveAct;
             QAction *saveAsAct;
             QAction *closeAct;
             QAction *exitAct;
             QAction *cutAct;
             QAction *copyAct;
             QAction *pasteAct;
             QAction *aboutAct;
             QAction *aboutQtAct
    ;
    وهى عبارة عن الActions/Menus/ToolBars
    isUntitled لتشير هل الملف لسه اول مرة ومش اتحفظ بإسم ولا لأ
    curFile لتشير للملف الحالى
    وبكدا يبقة خلص ال header
    الصورة النهائية ليه
    #ifndef MAINWINDOW_H
     #define MAINWINDOW_H
     #include <QMainWindow>
     class QAction;
     class QMenu;
     class QTextEdit;
     class MainWindow : public QMainWindow
     {
             Q_OBJECT
     public:
             MainWindow();
             MainWindow(const QString &fileName);
     protected:
             void closeEvent(QCloseEvent *event);
     private slots:
             void newFile();
             void open();
             bool save();
             bool saveAs();
             void about();
             void documentWasModified();
     private:
             void init();
             void createActions();
             void createMenus();
             void createToolBars();
             void createStatusBar();
             void readSettings();
             void writeSettings();
             bool maybeSave();
             void loadFile(const QString &fileName);
             bool saveFile(const QString &fileName);
             void setCurrentFile(const QString &fileName);
             QString strippedName(const QString &fullFileName);
             MainWindow *findMainWindow(const QString &fileName);
             QTextEdit *textEdit;
             QString curFile;
             bool isUntitled;
             QMenu *fileMenu;
             QMenu *editMenu;
             QMenu *helpMenu;
             QToolBar *fileToolBar;
             QToolBar *editToolBar;
             QAction *newAct;
             QAction *openAct;
             QAction *saveAct;
             QAction *saveAsAct;
             QAction *closeAct;
             QAction *exitAct;
             QAction *cutAct;
             QAction *copyAct;
             QAction *pasteAct;
             QAction *aboutAct;
             QAction *aboutQtAct;
     };
     #endif

    لاحظ ال images اللى فى ال Application هنستخدمها عن طريق ال resource file

    <!DOCTYPE RCC><RCC version="1.0">
     <qresource>
             <file>images/copy.png</file>
             <file>images/cut.png</file>
             <file>images/new.png</file>
             <file>images/open.png</file>
             <file>images/paste.png</file>
             <file>images/save.png</file>
     </qresource>
     </RCC>

    ندخل فى ال implementation
    هنحتاج نستخدم QtGui عشان ال widgets وال windows وهنحتاج نعمل include لل mainwindow.h
    #include <QtGui>
    #include "mainwindow.h"

    ال init method وهى تعتبر ال entry point اللى هيتم فيها التصميم لل gui وتجهيز ال window
    v
    oid MainWindow::init()
     {
             setAttribute(Qt::WA_DeleteOnClose);
             isUntitled = true;
             textEdit = new QTextEdit;
             setCentralWidget(textEdit);
             createActions();
             createMenus();
             createToolBars();
             createStatusBar();
             readSettings();
             connect(textEdit->document(), SIGNAL(contentsChanged()),
                             this, SLOT(documentWasModified()));
     }

    منطقى إن لما تبدأ البرنامج هيكون ال file الحالى مش ليه إسم فهنخلى ال isUntitle قيمتها true
    نعمل QtextEdit Object ونخليه فى سنتر الويندو لأن فوقه ال menu/toolbars وتحته ال statusbar
    createActions و createMenus و createToolsBars و createStatusBar بتنشئ لينا ال Actions/Menus/Toolbars/StatusBar

    ال Actions
    void MainWindow::createActions()
     {
             newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
             newAct->setShortcut(tr("Ctrl+N"));
             newAct->setStatusTip(tr("Create a new file"));
             connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
             openAct = new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
             openAct->setShortcut(tr("Ctrl+O"));
             openAct->setStatusTip(tr("Open an existing file"));
             connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
             saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
             saveAct->setShortcut(tr("Ctrl+S"));
             saveAct->setStatusTip(tr("Save the document to disk"));
             connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
             saveAsAct = new QAction(tr("Save &As..."), this);
             saveAsAct->setStatusTip(tr("Save the document under a new name"));
             connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
             closeAct = new QAction(tr("&Close"), this);
             closeAct->setShortcut(tr("Ctrl+W"));
             closeAct->setStatusTip(tr("Close this window"));
             connect(closeAct, SIGNAL(triggered()), this, SLOT(close()));
             exitAct = new QAction(tr("E&xit"), this);
             exitAct->setShortcut(tr("Ctrl+Q"));
             exitAct->setStatusTip(tr("Exit the application"));
             connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
             cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
             cutAct->setShortcut(tr("Ctrl+X"));
             cutAct->setStatusTip(tr("Cut the current selection's contents to the "
                                                             "clipboard"));
             connect(cutAct, SIGNAL(triggered()), textEdit, SLOT(cut()));
             copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this);
             copyAct->setShortcut(tr("Ctrl+C"));
             copyAct->setStatusTip(tr("Copy the current selection's contents to the "
                                                              "clipboard"));
             connect(copyAct, SIGNAL(triggered()), textEdit, SLOT(copy()));
             pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this);
             pasteAct->setShortcut(tr("Ctrl+V"));
             pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
                                                               "selection"));
             connect(pasteAct, SIGNAL(triggered()), textEdit, SLOT(paste()));
             aboutAct = new QAction(tr("&About"), this);
             aboutAct->setStatusTip(tr("Show the application's About box"));
             connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
             aboutQtAct = new QAction(tr("About &Qt"), this);
             aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
             connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
             cutAct->setEnabled(false);
             copyAct->setEnabled(false);
             connect(textEdit, SIGNAL(copyAvailable(bool)),
                             cutAct, SLOT(setEnabled(bool)));
             connect(textEdit, SIGNAL(copyAvailable(bool)),
                             copyAct, SLOT(setEnabled(bool)));
     }

    هشرح ال newAction بس والباقى نفس الفكرة
    newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
             newAct->setShortcut(tr("Ctrl+N"));
             newAct->setStatusTip(tr("Create a new file"));
             connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));

    ال Qaction Constructor بياخد 3 parameters ال أول ليشير لل Icon اللى فى الAction والتانى بيشير لل Text الظاهر على ال Action والتالت بيشير لل current ref وهو this
    setStatusTip وهى ال text اللى هيظهر فى ال statusBar كل ماتمر على الnew Action
    نربط ال triggered SIGNAL مع ال newFile SLOT ب Connect والsender هنا هيكون newAction وال receiver هيكون ال main window
    لاحظ
            aboutQtAct = new QAction(tr("About &Qt"), this);
             aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
             connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

    فى ال Connect هنا ال sender هو aboutQtAction وال receiver هو ال qApp وهو بيقدم slot بإسم aboutQt بتظهر ال about window الإفتراضية

    ال Copy/Cut/Paste stuff انت مش ليك دعوة بيهم كل اللى عليك تربط ال Action بال textEdit وتستخدم ال slot المناسبة سواء copy, cut or paste
    Keep it simple !
    ال setEnabled اعتقد واضحة وهى إنك تقدر ت trigger ال Action او لأ وبتاخد true/false
    void MainWindow::about()
     {
            QMessageBox::about(this, tr("About SDI"),
                             tr("The <b>SDI</b> example demonstrates how to write single "
                                    "document interface applications using Qt."));
     }


    بمجرد ضغطك على ال about action هيظهر messagebox لاحظ إنك تقدر تستخدم HTML tag

    إنشاء ال menus

    void MainWindow::createMenus()
     {
             fileMenu = menuBar()->addMenu(tr("&File"));
             fileMenu->addAction(newAct);
             fileMenu->addAction(openAct);
             fileMenu->addAction(saveAct);
             fileMenu->addAction(saveAsAct);
             fileMenu->addSeparator();
             fileMenu->addAction(closeAct);
             fileMenu->addAction(exitAct);
             editMenu = menuBar()->addMenu(tr("&Edit"));
             editMenu->addAction(cutAct);
             editMenu->addAction(copyAct);
             editMenu->addAction(pasteAct);
             menuBar()->addSeparator();
             helpMenu = menuBar()->addMenu(tr("&Help"));
             helpMenu->addAction(aboutAct);
             helpMenu->addAction(aboutQtAct);
     }

    كل اللى عليك إنك تستخدم addMenu method وتباصى ليها إسم ال Menu اللى هتبقة موجودة فى ال MenuBar
    وفى كل menu عملتها تضيف ال Actions الخاصة بيها بإستخدام addAction ولتضيف separator إستخدام addSeparator method
    عمل ال ToolBars بسيط جدا
    void MainWindow::createToolBars()
     {
             fileToolBar = addToolBar(tr("File"));
             fileToolBar->addAction(newAct);
             fileToolBar->addAction(openAct);
             fileToolBar->addAction(saveAct);
             editToolBar = addToolBar(tr("Edit"));
             editToolBar->addAction(cutAct);
             editToolBar->addAction(copyAct);
             editToolBar->addAction(pasteAct);
    }

    createStatusBar
    void MainWindow::createStatusBar()
     {
             statusBar()->showMessage(tr("Ready"));
     }

    maybeSave عشان نهدل save or not
    bool MainWindow::maybeSave()
     {
             if (textEdit->document()->isModified()) {
                     QMessageBox::StandardButton ret;
                     ret = QMessageBox::warning(this, tr("SDI"),
                                              tr("The document has been modified.\n"
                                                     "Do you want to save your changes?"),
                                              QMessageBox::Save | QMessageBox::Discard
                                              | QMessageBox::Cancel);
                     if (ret == QMessageBox::Save)
                             return save();
                     else if (ret == QMessageBox::Cancel)
                             return false;
             }
             return true;
     }

    وبناء على ال response هنشوف هنستخدم هنستخدم اى رد فعل
    loadFile
    void MainWindow::loadFile(const QString &fileName)
     {
             QFile file(fileName);
             if (!file.open(QFile::ReadOnly | QFile::Text)) {
                     QMessageBox::warning(this, tr("SDI"),
                                                              tr("Cannot read file %1:\n%2.")
                                                              .arg(fileName)
                                                              .arg(file.errorString()));
                     return;
             }
             QTextStream in(&file);
             QApplication::setOverrideCursor(Qt::WaitCursor);
             textEdit->setPlainText(in.readAll());
             QApplication::restoreOverrideCursor();
             setCurrentFile(fileName);
             statusBar()->showMessage(tr("File loaded"), 2000);
     }


    كل الفكرة هى عمل Qfile Object ونختبر هل الملف readOnly او لأ فى حال إنه متوافق معانا هنعمل QtextStream object ونباصى كل اللى فيه -readAll method- ل ال setPlainText الخاصة ب textEdit
    لاحظ موضوع ال Qt::WaitCursor عشان نخلى الcursor باين إن فى بروسس شغالة
    ال restoreOverrideCursor بنستعيد الcursor بصورته السابقة.
    نخلى إسم ال currentFile هو إسم ال Opened File بإستخدام setCurrentFile ونشير فى ال statusBar ان ال File Loaded بإستخدام ال showMessage.
    QString MainWindow::strippedName(const QString &fullFileName)
     {
             return QFileInfo(fullFileName).fileName();
     }

    للحصول على اسم ال File فقط نستخدم fileName method تحت ال QfileInfo وهى بتدى return ل Qstring بالإسم المختصر لل File


    setCurrentFile
    void MainWindow::setCurrentFile(const QString &fileName)
     {
             static int sequenceNumber = 1;
             isUntitled = fileName.isEmpty();
             if (isUntitled) {
                     curFile = tr("document%1.txt").arg(sequenceNumber++);
             } else {
                     curFile = QFileInfo(fileName).canonicalFilePath();
             }
             textEdit->document()->setModified(false);
             setWindowModified(false);
             setWindowTitle(tr("%1[*] - %2").arg(strippedName(curFile))
                                                                                    .arg(tr("SDI")));
     }



    عمل Save لل File
    bool MainWindow::saveFile(const QString &fileName)
     {
             QFile file(fileName);
             if (!file.open(QFile::WriteOnly | QFile::Text)) {
                     QMessageBox::warning(this, tr("SDI"),
                                                              tr("Cannot write file %1:\n%2.")
                                                              .arg(fileName)
                                                              .arg(file.errorString()));
                     return false;
             }
             QTextStream out(&file);
             QApplication::setOverrideCursor(Qt::WaitCursor);
             out << textEdit->toPlainText();
             QApplication::restoreOverrideCursor();
             setCurrentFile(fileName);
             statusBar()->showMessage(tr("File saved"), 2000);
             return true;
     }

    Save/Save As
    bool MainWindow::save()
     {
             if (isUntitled) {
                     return saveAs();
             } else {
                     return saveFile(curFile);
             }

    }
     bool MainWindow::saveAs()
     {
             QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),
                                                                                                             curFile);
             if (fileName.isEmpty())
                     return false;
             return saveFile(fileName);
     }

    فى حال لو ال currentFile ليه اسم يعنى isUntitled هتدى false هيتم إستدعاء saveFile method
    فى حال لو مش ليه إسم او isUntitled هتدى true هيتم إستدعاء saveAs method وهى هتحفظ ال file ب save file dialog لطيف للمستخدم


    بالمناسبة فى حالة ال newFileAction هيتعمل Object جديد من ال mainwindow وهكذا على بعد 40 و 40 من ال x, y اللى بادئ عنهم ال window
     void MainWindow::newFile()
     {
             MainWindow *other = new MainWindow;
             other->move(x() + 40, y() + 40);
             other->show();
     }


    واخيرا ال main.cpp وهو ال Entry point للبرنامج
     #include <QApplication>

     #include "mainwindow.h"

     int main(int argc, char *argv[])
     {
             Q_INIT_RESOURCE(sdi);
             QApplication app(argc, argv);
             MainWindow *mainWin = new MainWindow;
             mainWin->show();
             return app.exec();
     }


    Q_INIT_RESOURCE بنباصى ليها إسم ملف ال resource المستخدم
    كفاية كلام لحد كدا باقى السورس بسيط
    المرة الجاية نبقة نعمل MDI Application

    ال source من ال QT Examples فى mainwindow/sdi

    كلمات مفتاحية  :
    Qtexteditor SIMPLE SDI Application

    تعليقات الزوار ()