Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Пишем сайт с новостями на Wt

Anna | 24.06.2014 | нет комментариев
Для начала расскажу немножко о себе. Я студент 4 курса МАИ специальности «ЭВМ, комплексы, системы и сети», а также начинающий программист на С /Qt. Дюже давным-давно я хотел обучиться веб-разработке, но до постижения всех нужных языков и спецтехнологий руки никак не доходили. Незадолго на Прогре возникластатья о создании веб-приложений с поддержкой C библиотеки Wt, и я решил поближе познакомиться с этой библиотекой.

Подготовка рабочего места

Каждый код я писал под Gentoo-linux в Qt Creator. Если вы решите делать так же, то для начала придётся подготовить окружение под наши нужды.
Первое, что нужно сделать — это сделать план. Я применял «Примитивный план на С » без поддержки Qt. Правда Wt дозволено применять коллективно с Qt, в данном случае нам это не потребуется.

Я назвал план MyApp. Дальше откроем файл MyApp.pro и немножко его отредактируем. А именно, в моём случае, нужно добавить такие строки:

LIBS = -L/usr/lib -lwt -lwthttp -lwtdbo -lwtdbosqlite3 -I/usr/local/include
LIBS = -L/usr/local/lib -lwthttp -lwt -lboost_regex -lboost_signals
LIBS = -lboost_system -lboost_thread -lboost_filesystem -lboost_date_time -lpthread -lcrypt

Ещё нам нужно будет слинковать папку resources в то место, откуда мы будем запускать наш сайт. Скажем, так:
ln -s /usr/share/Wt/resources/ ~/build-MyApp-Qt5-Отладка/

Подготовку на этом дозволено считать завершенной.

Выходит, начнём…

Дабы запустить пустое приложение, довольно будет написать такой код:

#include <iostream>
#include <Wt/WServer>
#include <Wt/WApplication>

using namespace Wt;

WApplication *createWidget(const WEnvironment& env)
{
    WApplication *app=new WApplication(env); //Создаём пустое веб-приложение
    app->setTitle("My Site"); //Устанавливаем заголовок страницы (то же, что в html <title></title>)
    app->setTheme(new Wt::WBootstrapTheme());  //Будем применять жанры bootstrap
    return app;
}

int main(int argc, char **argv)
{
  Wt::WServer server(argv[0]); //Создаём сервер

  server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION); //Конфигурируем его

  server.addEntryPoint(Wt::Application,createWidget); //Добавляем "точку входа"

  if (server.start()) {
    int sig = Wt::WServer::waitForShutdown(); //Если заработало, ждём заключения
    std::cerr << "Shutting down: (signal = " << sig << ")" << std::endl;
    server.stop();
  }
}

Мы можем запустить всё это на localhost на порту 8080 командой:

./myapp --docroot . --http-address 0.0.0.0 --http-port 8080

Процесс запуска дозволено автоматизировать, для этого параметры запуска необходимо прописать в строке «Планы->Запуск->Параметры»

Таким образом, мы получаем веб-сервер с пустой страничкой, доступ к которой дозволено получить по адресу http://localhost:8080/

Добавим меню.

Приступим к заполнению. Для начала сделаем меню для нашего сайта. Для этого сделаем новейший класс, я назвал его «Page».
page.h:

#ifndef PAGE_H
#define PAGE_H

#include <Wt/WContainerWidget>
#include <Wt/WText>
#include <Wt/WString>
#include <Wt/WNavigationBar>
#include <Wt/WMenu>
#include <Wt/WStackedWidget>

class Page : public Wt::WContainerWidget
{
public:
    Page(WContainerWidget *parent = 0);
private:
    Wt::WStackedWidget *contentsStack;
    Wt::WNavigationBar *NavBar;
    Wt::WMenu *LeftMenu;
};

#endif // PAGE_H

page.cpp:

#include "page.h"

using namespace Wt;

Page::Page(WContainerWidget *parent):WContainerWidget(parent)
{
    setStyleClass("container");
    contentsStack = new Wt::WStackedWidget(); //В этом "контейнере" будет возникать виджет, соответствующий нынешнему пункту меню
    contentsStack->setStyleClass("container");
    contentsStack->setPadding(48,Wt::Top); //Потому, что меню будет фиксированным сверху и закроет собой часть этого "контейнера"

    NavBar = new WNavigationBar(this); //Сама полосочка меню
    NavBar->setTitle("MyApp","http://localhost:8080"); //Красивый загw Wt::WPanel();
        panel->setTitle(Article.get()->title);
        panel->setCentralWidget(new Wt::WText(WString::fromUTF8("<p>Автор:") Article.get()->author "</p><p>" Article.get()->text "</p>"));
        NewsTable->elementAt(j,0)->addWidget(panel);
        j  ;
    }
    transaction1.commit();//Закрыли транзакцию. Кстати, вторично транзакции применять невозможно.

    setStyleClass("container");
    contentsStack = new Wt::WStackedWidget();
    contentsStack->setStyleClass("container");
    contentsStack->setPadding(48,Wt::Top);

    NavBar = new WNavigationBar(this);
    NavBar->setTitle("MyApp","http://cursed.redegrade.net");
    NavBar->setResponsive(true);
    NavBar->addStyleClass("container");
    NavBar->setPositionScheme(Wt::Fixed);
    LeftMenu=new WMenu(contentsStack,this);
    NavBar->addMenu(LeftMenu);

    LeftMenu->addItem(WString::fromUTF8("Новости"),NewsTable); //Прикручиваем нашу табличку с новостями к пункту меню.

    this->addWidget(contentsStack);
}

Ну, по поводу итога новостей всё ясно, а как же создание?

Хм, и правда. Куда без создания. Теперь прикрутим. Придётся переписать класс Page ещё раз, заключительный в пределах статьи.

page.h:

#ifndef PAGE_H
#define PAGE_H

#include <Wt/WContainerWidget>
#include <Wt/WText>
#include <Wt/WString>
#include <Wt/WNavigationBar>
#include <Wt/WMenu>
#include <Wt/WTable>
#include <Wt/WStackedWidget>
#include <Wt/Dbo/Session>

class Page : public Wt::WContainerWidget
{
public:
    Page(WContainerWidget *parent = 0);
private:
    Wt::WStackedWidget *contentsStack;
    Wt::WNavigationBar *NavBar;
    Wt::WMenu *LeftMenu;
    Wt::WTable *CreateArticle;
    Wt::WLineEdit *Title;
    Wt::WLineEdit *Author;
    Wt::WTextArea *Text;
    Wt::WPushButton *AddNews;
    Wt::Dbo::Session DBSession;
    void AddArticle();
};

#endif // PAGE_H

page.cpp

#include "page.h"
#include "news.h"
#include <Wt/WApplication>
#include <Wt/WPanel>
#include <Wt/WLineEdit>
#include <Wt/WTextEdit>
#include <Wt/WPushButton>
#include <Wt/Dbo/backend/Sqlite3>

using namespace Wt;

Page::Page(WContainerWidget *parent):WContainerWidget(parent)
{
    Wt::Dbo::backend::Sqlite3 DataBase=WApplication::instance()->appRoot()   "myapp.db";
    DBSession.setConnection(DataBase);

    DBSession.mapClass<News>("news");

    Wt::Dbo::Transaction transaction(DBSession);
    try {
        DBSession.createTables();
        Wt::log("info") << "Database created";
    } catch (...) {
        Wt::log("info") << "Using existing database";
    }
    transaction.commit();

    Wt::WTable *NewsTable=new Wt::WTable();
    NewsTable->addStyleClass("container");

    Wt::Dbo::Transaction transaction1(DBSession);
    Wt::Dbo::collection<Wt::Dbo::ptr<News> > a=DBSession.find<News>().orderBy("created desc");
    int j=0;
    for (Wt::Dbo::collection<Wt::Dbo::ptr<News> >::const_iterator i = a.begin(); i != a.end();   i) {
        Wt::Dbo::ptr<News> Article = *i;
        Wt::WPanel *panel = new Wt::WPanel();
        panel->setTitle(WString::fromUTF8(Article.get()->title));
        panel->setCentralWidget(new Wt::WText(WString::fromUTF8("<p>Автор:") WString::fromUTF8(Article.get()->author) "</p><p>" WString::fromUTF8(Article.get()->text) "</p>"));//Немного поправил итог. Из коробки норовит выводить русский текст знаками вопроса.
        NewsTable->elementAt(j,0)->addWidget(panel);
        NewsTable->elementAt(j,0)->setLoadLaterWhenInvisible(true);
        j  ;
    }
    transaction1.commit();

    setStyleClass("container");
    contentsStack = new Wt::WStackedWidget();
    contentsStack->setStyleClass("container");
    contentsStack->setPadding(48,Wt::Top);

    NavBar = new WNavigationBar(this);
    NavBar->setTitle("MyApp","http://localhost:8080");
    NavBar->setResponsive(true);
    NavBar->addStyleClass("container");
    NavBar->setPositionScheme(Wt::Fixed);
    LeftMenu=new WMenu(contentsStack,this);
    NavBar->addMenu(LeftMenu);

    LeftMenu->addItem(WString::fromUTF8("Новости"),NewsTable);

    CreateArticle=new Wt::WTable(); //Табличка для формы создания новости
    Title=new Wt::WLineEdit(WString::fromUTF8("Заголовок новости")); //Всякие поля
    Author=new Wt::WLineEdit(WString::fromUTF8("Автор"));
    Text=new Wt::WTextArea(WString::fromUTF8("Текст новости"));
    AddNews=new Wt::WPushButton(WString::fromUTF8("Добавить новость"));

    CreateArticle->addStyleClass("container");

    CreateArticle->elementAt(0,0)->addWidget(Title); //Добавляем поля в табличку
    CreateArticle->elementAt(1,0)->addWidget(Author);
    CreateArticle->elementAt(2,0)->addWidget(Text);
    CreateArticle->elementAt(3,0)->addWidget(AddNews);

    LeftMenu->addItem(WString::fromUTF8("Создать новость"),CreateArticle); //Создаём кнопку и привязываем способ Page::AddArticle к её нажатию
    AddNews->clicked().connect(this,&Page::AddArticle);

    this->addWidget(contentsStack);
}

void Page::AddArticle()
{
    Wt::Dbo::backend::Sqlite3 DataBase=WApplication::instance()->appRoot()   "myapp.db";
    DBSession.setConnection(DataBase); //Переподключаемся (длинно с этим дрался, допустимо, стоило сделать всё переменными класса, а не локальными)
    Wt::Dbo::Transaction transaction(DBSession); //Повторюсь: для всякой операции с БД необходима живая транзакция.
    News *a=new News(); //Создаём новость
    a->title=Title->text().toUTF8();
    a->author=Author->text().toUTF8();
    a->text=Text->text().toUTF8();
    Wt::Dbo::ptr<News> Article=DBSession.add(a); //Заносим новость в БД
}

Итог:


P.S. Если нужны добавочные пояснения, пишите в комментариях, постараюсь рассказать подробней. Я только начал постигать Wt, следственно, абсолютно допустимо, где-то неправ. Буду рад, если исправите.
P.P.S. Если вам увлекательны статьи по Wt, пишите в комментариях, что ещё вы хотели бы о нём узнать, и я постараюсь написать об этом!

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB