إعـــــــلان

تقليص
لا يوجد إعلان حتى الآن.

QTextEditor, SIMPLE SDI Application

تقليص
X
 
  • تصفية - فلترة
  • الوقت
  • عرض
إلغاء تحديد الكل
مشاركات جديدة

  • QTextEditor, SIMPLE SDI Application

    SDI Application


    لاحظ إن ال 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

    ADIOS PPL!
    الملفات المرفقة
    التعديل الأخير تم بواسطة StrikerX; الساعة 26-05-2008, 09:28 AM.
    Programming-Fr34ks[dot]NET
    Ma Weblog
    ابدأ بتعلم Python | Ruby
    كتاب البايثون متوافر الآن
    لا اتواجد بهذا المنتدى ... للإتصال

  • #2
    اخبار ال sheep معاك ايه سمعت انها هي كمان جالها عبط
    ربنا يعينا علي عبط الخرفان
    يسلم ماوسك وكيبورد وشاشتك وال cpu بتاعت علي الموضوع الجميل ده -انت لا -
    BOOOF , I AM GONE
    Still , you gotta wait for my PRESENT :D
    C programming arabic Tutorial|Programming-fr34ks

    تعليق


    • #3
      خبار ال sheep معاك ايه سمعت انها هي كمان جالها عبط
      ربنا يعينا علي عبط الخرفان
      ههههههههههههههههه back off مش طالبة هى ههههههههههههههه
      Shepherd :P

      يسلم ماوسك وكيبورد وشاشتك وال cpu بتاعت علي الموضوع الجميل ده -انت لا -
      الله يخليك يابنى كفاية إنك عديت هههههههههه
      Programming-Fr34ks[dot]NET
      Ma Weblog
      ابدأ بتعلم Python | Ruby
      كتاب البايثون متوافر الآن
      لا اتواجد بهذا المنتدى ... للإتصال

      تعليق


      • #4
        درس ممتاز اخي سترايكر ،،

        go ahead
        &
        Good Luck

        تعليق


        • #5
          نورت SudaNix
          Programming-Fr34ks[dot]NET
          Ma Weblog
          ابدأ بتعلم Python | Ruby
          كتاب البايثون متوافر الآن
          لا اتواجد بهذا المنتدى ... للإتصال

          تعليق

          يعمل...
          X