精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解 QT 源碼之QT元對象系統和信號槽機制

移動開發
本文介紹的是QT 源碼之QT元對象系統和信號槽機制,QT的信號和槽機制是用來在對象間通訊的方法,當一個特定事件發生的時候,signal會被 emit 出來,slot 調用是用來響應相應的 signal 的.

QT 源碼之QT元對象系統和信號槽機制是本文要介紹的內容。QT信號機制是用來在對象間通訊的方法,當一個特定事件發生的時候,signal會被 emit 出來,slot 調用是用來響應相應的 signal 的。簡單點說就是如何在一個類的一個函數中觸發另一個類的另一個函數調用,而且還要把相關的參數傳遞過去.好像這和回調函數也有點關系,但是消息機制可比回調函數有用多了,也復雜多了。

下面的代碼是我寫的一個繼承QLabel的類,是QLabel可以響應鼠標單擊的消息。

  1. view plaincopy to clipboardprint?  
  2. #include <QLabel>     
  3. #include <QWidget>     
  4. #include <QMessageBox>     
  5. #include <QApplication>     
  6. class ClickedLabel : public QLabel     
  7. {     
  8.     Q_OBJECT     
  9. signals:     
  10.     void Clicked(ClickedLabel* clicked);     
  11. public:     
  12.     ClickedLabel(const QString &text,QWidget *parent=0): QLabel(text,parent){   };     
  13.     ~ClickedLabel() {};     
  14. protected:     
  15.     void mouseReleaseEvent( QMouseEvent* ){emit Clicked(this);};     
  16. public slots:     
  17.     void OnCLicked( ClickedLabel* ) {QMessageBox::information(topLevelWidget(), "Message from Qt", "Label Clicked!");   };     
  18. };     
  19. #include "main.moc"     
  20. int main(int argc,char* argv[])     
  21. {     
  22.     QApplication app(argc,argv);     
  23.     ClickedLabel label("<h2>test</h2>");     
  24.     QObject::connect( &label, SIGNAL( Clicked(ClickedLabel*) ),&label, SLOT( OnCLicked(ClickedLabel*) ) ) ;     
  25.     label.show();     
  26.     return app.exec();     
  27. }    
  28. #include <QLabel> 
  29. #include <QWidget> 
  30. #include <QMessageBox> 
  31. #include <QApplication> 
  32. class ClickedLabel : public QLabel  
  33. {  
  34.  Q_OBJECT  
  35. signals:  
  36.  void Clicked(ClickedLabel* clicked);  
  37. public:  
  38.  ClickedLabel(const QString &text,QWidget *parent=0): QLabel(text,parent){ };  
  39.  ~ClickedLabel() {};  
  40. protected:  
  41.  void mouseReleaseEvent( QMouseEvent* ){emit Clicked(this);};  
  42. public slots:  
  43.  void OnCLicked( ClickedLabel* ) {QMessageBox::information(topLevelWidget(), "Message from Qt", "Label Clicked!"); };  
  44. };  
  45. #include "main.moc"  
  46. int main(int argc,char* argv[])  
  47. {  
  48.  QApplication app(argc,argv);  
  49.  ClickedLabel label("<h2>test</h2>");  
  50.  QObject::connect( &label, SIGNAL( Clicked(ClickedLabel*) ),&label, SLOT( OnCLicked(ClickedLabel*) ) ) ;  
  51.  label.show();  
  52.  return app.exec();  

這段代碼很簡單,講述了QT的singal和slot的使用。下面我們就深入QT的源碼內部,來看一看QT是如何實現singal和slots的。

#include “main.moc” 的意思就是使編譯器找到moc對Q_OBJECT處理后的標準C++文件。編譯的時候我們需要首先在該目錄中使用 qmake -project 生成一個 .pro 文件,該文件含有工程細節,然后使用 qmake 產生 Makefile,最后 nmake 就可以產生可執行文件了。我們看看在nmake之后除了生成目標代碼和可執行文件之外,還有一個main.moc文件,這個文件是moc產生的一個中間文件。

現在我們要看一下Q_OBJECT宏到底是什么?他與main.moc有什么關聯呢?相信我介紹完了Q_OBJECT宏之后,再看main.moc就能明白其所有函數的含義了。我們先到objectdefs.h 文件中看一下Q_OBJECT宏的定義:

  1. #define Q_OBJECT \  
  2. public: \  
  3.  Q_OBJECT_CHECK \  
  4.  static const QMetaObject staticMetaObject; \  
  5.  virtual const QMetaObject *metaObject() const; \  
  6.  virtual void *qt_metacast(const char *); \  
  7.  QT_TR_FUNCTIONS \  
  8.  virtual int qt_metacall(QMetaObject::Call, int, void **); \  
  9. private: 

1首先調用了 Q_OBJECT_CHECK (插入了一個 qt_check_for_QOBJECT_macro 的 template function)

2  然后是全局常量 QMetaObject 對象,因此可以用 QClassname::staticMetaObject 直接訪問,另外提供了兩個接口函數 metaObject() 用于不同的 class 返回自己的 staticMetaObject、qt_metacast() 用于轉換,我們在 moc 產生的文件里面可以找到這兩個接口的實現:

  1. const QMetaObject *ClickedLabel::metaObject() const  
  2. {  
  3.     return &staticMetaObject;  
  4. }  
  5. void *ClickedLabel::qt_metacast(const char *_clname)  
  6. {  
  7.     if (!_clname) return 0;  
  8.     if (!strcmp(_clname, qt_meta_stringdata_ClickedLabel))  
  9.         return static_cast<void*>(const_cast< ClickedLabel*>(this));  
  10.     return QLabel::qt_metacast(_clname);  
  11. }  
  12. 3  宏QT_TR_FUNCTIONS是和i18n相關的,我們暫時不用去管它。  
  13. #  define QT_TR_FUNCTIONS \  
  14.     static inline QString tr(const char *s, const char *c = 0) \  
  15.         { return staticMetaObject.tr(s, c); }  
  16.  
  17. 4         最后是接口函數qt_metacall,他的作用是查表,調用函數  
  18. int ClickedLabel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)  
  19. {  
  20.     _id = QLabel::qt_metacall(_c, _id, _a);  
  21.     if (_id < 0)  
  22.         return _id;  
  23.     if (_c == QMetaObject::InvokeMetaMethod) {  
  24.         switch (_id) {  
  25.         case 0: Clicked((*reinterpret_cast< ClickedLabel*(*)>(_a[1]))); break;  
  26.         case 1: OnCLicked((*reinterpret_cast< ClickedLabel*(*)>(_a[1]))); break;  
  27.         }  
  28.         _id -2;  
  29.     }  
  30.     return _id;  
  31. }  
  32. 我們來仔細看看 QMetaObject,這就是meta-object的數據結構定義   
  33. struct Q_CORE_EXPORT QMetaObject  
  34. {  
  35.  const char *className() const;  
  36.  const QMetaObject *superClass() const;  
  37.  QObject *cast(QObject *obj) const;  
  38.  // ...  
  39.  struct { // private data  
  40.    const QMetaObject *superdata;  
  41.    const char *stringdata;  
  42.    const uint *data;  
  43.    const void *extradata;  
  44.  } d;  
  45. } ; 

#p#

下面看看我們生成的具體的代碼:

  1. static const uint qt_meta_data_ClickedLabel[] = {  
  2.  // content:  
  3.        1,       // revision  
  4.        0,       // classname  
  5.        0,    0, // classinfo  
  6.        2,   10, // methods  
  7.       0,    0, // properties  
  8.        0,    0, // enums/sets  
  9.  // signals: signature, parameters, type, tag, flags  
  10.       22,   14,   13,   13, 0x05,  
  11.  // slots: signature, parameters, type, tag, flags  
  12.       45,   13,   13,   13, 0x0a,  
  13.        0        // eod  
  14. };  
  15. static const char qt_meta_stringdata_ClickedLabel[] = {  
  16.     "ClickedLabel\0\0clicked\0Clicked(ClickedLabel*)\0"  
  17.     "OnCLicked(ClickedLabel*)\0"  
  18. };  
  19. const QMetaObject ClickedLabel::staticMetaObject = {  
  20.     { &QLabel::staticMetaObject, qt_meta_stringdata_ClickedLabel,  
  21.       qt_meta_data_ClickedLabel, 0 }  
  22. }; 

這就是meta-object的初始化代碼,meta-object包含所有繼承QObject類的元對象信息。包括class name, superclass name, properties, signals and slots等等。

ClickedLabel的staticMetaObject初始化用到了QLabel::staticMetaObject,

qt_meta_stringdata_ClickedLabel是元數據的簽名

qt_meta_data_ClickedLabel,是元數據的索引數組指針。

qt_meta_data_ClickedLabel中這些莫名其妙的數字是如何變成QMetaObject的呢?

在qmetaobject.cpp中我們找到了QMetaObjectPrivate的定義:

  1. struct QMetaObjectPrivate  
  2. {  
  3.     int revision;  
  4.     int className;  
  5.     int classInfoCount, classInfoData;  
  6.     int methodCount, methodData;  
  7.     int propertyCount, propertyData;  
  8.     int enumeratorCount, enumeratorData;  
  9. }; 

很明顯,利用qt_meta_data_ClickedLabel中存儲的索引和qt_meta_stringdata_ClickedLabel中存儲的值,我們很容易將QMetaObject構建起來。這中間的轉換是通過

  1. static inline const QMetaObjectPrivate *priv(const uint* data)  
  2. { return reinterpret_cast<const QMetaObjectPrivate*>(data); } 

這個函數來完成的。

#p#

下面我們著重看看幾個與 signal/slot 相關的代碼

qobject.cpp 文件中關于 QObject::connect() 函數的代碼,

  1. bool QObject::connect(const QObject *sender, const char *signal,  
  2.                      const QObject *receiver, const char *method,  
  3.                       Qt::ConnectionType type)  
  4. {  
  5.     {  
  6.         const void *cbdata[] = { sender, signal, receiver, method, &type };  
  7.         if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))  
  8.             return true;  
  9.     }  
  10. #ifndef QT_NO_DEBUG  
  11.     bool warnCompat = true;  
  12. #endif  
  13.     if (type == Qt::AutoCompatConnection) {  
  14.         type = Qt::AutoConnection;  
  15. #ifndef QT_NO_DEBUG  
  16.         warnCompat = false;  
  17. #endif  
  18.     }  
  19.     //判斷是否是NULL  
  20.     if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {  
  21.         qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",  
  22.                  sender ? sender->metaObject()->className() : "(null)",  
  23.                  (signal && *signal) ? signal+1 : "(null)",  
  24.                  receiver ? receiver->metaObject()->className() : "(null)",  
  25.                  (method && *method) ? method+1 : "(null)");  
  26.         return false;  
  27.     }  
  28.     QByteArray tmp_signal_name;  
  29.     if (!check_signal_macro(sender, signal, "connect", "bind"))  
  30.         return false;  
  31.     const QMetaObject *smeta = sender->metaObject();  
  32.     ++signal; //skip code  
  33.     int signal_index = smeta->indexOfSignal(signal);  
  34.     if (signal_index < 0) {  
  35.         // check for normalized signatures  
  36.         tmp_signal_name = QMetaObject::normalizedSignature(signal).prepend(*(signal - 1));  
  37.         signal = tmp_signal_name.constData() + 1;  
  38.         signal_index = smeta->indexOfSignal(signal);  
  39.        if (signal_index < 0) {  
  40.             err_method_notfound(QSIGNAL_CODE, sender, signal, "connect");  
  41.             err_info_about_objects("connect", sender, receiver);  
  42.             return false;  
  43.         }  
  44.     }  
  45.     QByteArray tmp_method_name;  
  46.     int membcode = method[0] - '0';  
  47.     if (!check_method_code(membcode, receiver, method, "connect"))  
  48.         return false;  
  49.     ++method; // skip code  
  50.     const QMetaObject *rmeta = receiver->metaObject();  
  51.     int method_index = -1;  
  52.     switch (membcode) {  
  53.     case QSLOT_CODE:  
  54.         method_index = rmeta->indexOfSlot(method);  
  55.         break;  
  56.     case QSIGNAL_CODE:  
  57.         method_index = rmeta->indexOfSignal(method);  
  58.         break;  
  59.     }  
  60.     if (method_index < 0) {  
  61.         // check for normalized methods  
  62.         tmp_method_name = QMetaObject::normalizedSignature(method);  
  63.         method = tmp_method_name.constData();  
  64.         switch (membcode) {  
  65.         case QSLOT_CODE:  
  66. method_index = rmeta->indexOfSlot(method);  
  67.             break;  
  68.         case QSIGNAL_CODE:  
  69.             method_index = rmeta->indexOfSignal(method);  
  70.            break;  
  71.         }  
  72.     }  
  73.     if (method_index < 0) {  
  74.         err_method_notfound(membcode, receiver, method, "connect");  
  75.         err_info_about_objects("connect", sender, receiver);  
  76.         return false;  
  77.     }  
  78.     if (!QMetaObject::checkConnectArgs(signal, method)) {  
  79.         qWarning("QObject::connect: Incompatible sender/receiver arguments"  
  80.                  "\n\t%s::%s --> %s::%s",  
  81.                  sender->metaObject()->className(), signal,  
  82.                  receiver->metaObject()->className(), method);  
  83.         return false;  
  84.     }  
  85.     int *types = 0;  
  86.     if ((type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)  
  87.             && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))  
  88.         return false;  
  89. #ifndef QT_NO_DEBUG  
  90.     {  
  91.         QMetaMethod smethod = smeta->method(signal_index);  
  92.         QMetaMethod rmethod = rmeta->method(method_index);  
  93.         if (warnCompat) {  
  94.             if(smethod.attributes() & QMetaMethod::Compatibility) {  
  95.                 if (!(rmethod.attributes() & QMetaMethod::Compatibility))  
  96.                     qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", smeta->className(), signal);  
  97.             } else if(rmethod.attributes() & QMetaMethod::Compatibility && membcode != QSIGNAL_CODE) {  
  98.                 qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",  
  99.                          smeta->className(), signal, rmeta->className(), method);  
  100.             }  
  101. }  
  102.     }  
  103. #endif  
  104.     QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);  
  105.     const_cast<QObject*>(sender)->connectNotify(signal - 1);  
  106.     return true;  

上面這段代碼首先調用了 QInternal 這個 namespace 里面 activateCallbacks 這個函數,然后根據 QMetaObject 信息檢查了 sender、receiver 以及對應 signal/slots 的匹配性,得到元數據類。把 signal/slot 字符串轉換成為了對應的 index,然后檢查信號的參數是否一致,函數的參數可以小于信號函數的參數。

最后得到method的元數據QMetaMethod,然后調用QMetaObject::connect的方法。

  1. bool QMetaObject::connect(const QObject *sender, int signal_index,  
  2.                           const QObject *receiver, int method_index, int type, int *types)  
  3. {  
  4.     QConnectionList *list = ::connectionList();  
  5.     if (!list)  
  6.         return false;  
  7.     QWriteLocker locker(&list->lock);  
  8.     list->addConnection(const_cast<QObject *>(sender), signal_index,  
  9.                         const_cast<QObject *>(receiver), method_index, type, types);  
  10.     return true;  

QMetaObject::connect代碼中QWriteLocker是為了防止多線程操作引起問題。

一旦我們發送了信號,就應該調用相關中的方法了,這個過程其實就是查找全局的connect列表的過程。真正發出信號是在main.moc中。

  1. void ClickedLabel::Clicked(ClickedLabel * _t1)  
  2. {  
  3.     void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };  
  4.     QMetaObject::activate(this, &staticMetaObject, 0, _a);  
  5. }  
  6. void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)  
  7. {  
  8.  // 這里得到的是QObject的數據,首先判斷是否為阻塞設置  
  9.     if (sender->d_func()->blockSig)  
  10.         return;  
  11.  // 得到全局鏈表  
  12.     QConnectionList * const list = ::connectionList();  
  13.     if (!list)  
  14.         return;  
  15.     QReadLocker locker(&list->lock);  
  16.     void *empty_argv[] = { 0 };  
  17.     if (qt_signal_spy_callback_set.signal_begin_callback != 0) {  
  18.         locker.unlock();  
  19.         qt_signal_spy_callback_set.signal_begin_callback(sender, from_signal_index,   argv ? argv : empty_argv);  
  20.         locker.relock();  
  21.     }  
  22.  // 在sender的哈希表中得到sender的連接  
  23.     QConnectionList::Hash::const_iterator it = list->sendersHash.find(sender);  
  24.     const QConnectionList::Hash::const_iterator end = list->sendersHash.constEnd();  
  25.     if (it == end) {  
  26.         if (qt_signal_spy_callback_set.signal_end_callback != 0) {  
  27.             locker.unlock();  
  28.           qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);  
  29.             locker.relock();  
  30.         }  
  31.         return;  
  32.     }  
  33.     QThread * const currentThread = QThread::currentThread();  
  34.     const int currentQThreadId = currentThread ? QThreadData::get(currentThread)->id : -1;  
  35.  // 記錄sender連接的索引  
  36.     QVarLengthArray<int> connections;  
  37.     for (; it != end && it.key() == sender; ++it) {  
  38.         connections.append(it.value());  
  39.   // 打上使用標記,因為可能是放在隊列中  
  40.         list->connections[it.value()].inUse = 1;  
  41.     }  
  42.     for (int i = 0; i < connections.size(); ++i) {  
  43.         const int at = connections.constData()[connections.size() - (i + 1)];  
  44.         QConnectionList * const list = ::connectionList();  
  45.   // 得到連接  
  46.         QConnection &c = list->connections[at];  
  47.         c.inUse = 0;  
  48.         if (!c.receiver || (c.signal < from_signal_index || c.signal > to_signal_index))  
  49.             continue;  
  50.   // 判斷是否放到隊列中  
  51.         // determine if this connection should be sent immediately or  
  52.         // put into the event queue  
  53.         if ((c.type == Qt::AutoConnection  
  54.              && (currentQThreadId != sender->d_func()->thread  
  55.                  || c.receiver->d_func()->thread != sender->d_func()->thread))  
  56.            || (c.type == Qt::QueuedConnection)) {  
  57.            ::queued_activate(sender, c, argv);  
  58.             continue;  
  59.         }  
  60.   // 為receiver設置當前發送者  
  61.         const int method = c.method;  
  62.         QObject * const previousSender = c.receiver->d_func()->currentSender;  
  63.         c.receiver->d_func()->currentSender = sender;  
  64.         list->lock.unlock();  
  65.        if (qt_signal_spy_callback_set.slot_begin_callback != 0)  
  66.          qt_signal_spy_callback_set.slot_begin_callback(c.receiver, method, argv ? argv : empty_argv);  
  67. #if defined(QT_NO_EXCEPTIONS)  
  68.         c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);  
  69. #else  
  70.        try {  
  71.    // 調用receiver的方法  
  72.             c.receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);  
  73.  
  74.         } catch (...) {  
  75.             list->lock.lockForRead();  
  76.             if (c.receiver)  
  77.                 c.receiver->d_func()->currentSender = previousSender;  
  78.             throw;  
  79.         }  
  80. #endif  
  81.         if (qt_signal_spy_callback_set.slot_end_callback != 0)  
  82.             qt_signal_spy_callback_set.slot_end_callback(c.receiver, method);  
  83.         list->lock.lockForRead();  
  84.         if (c.receiver)  
  85.             c.receiver->d_func()->currentSender = previousSender;  
  86.     }  
  87.     if (qt_signal_spy_callback_set.signal_end_callback != 0) {  
  88.         locker.unlock();  
  89.         qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);  
  90.         locker.relock();  
  91.     }  

響應信號也是在main.moc中實現的。

 

  1. int ClickedLabel::qt_metacall(QMetaObject::Call _c, int _id, void **_a)  
  2. {  
  3.     _id = QLabel::qt_metacall(_c, _id, _a);  
  4.     if (_id < 0)  
  5.         return _id;  
  6.     if (_c == QMetaObject::InvokeMetaMethod) {  
  7.         switch (_id) {  
  8.         case 0: Clicked((*reinterpret_cast< ClickedLabel*(*)>(_a[1]))); break;  
  9.         case 1: OnCLicked((*reinterpret_cast< ClickedLabel*(*)>(_a[1]))); break;  
  10.         }  
  11.         _id -2;  
  12.     }  
  13.     return _id;  

小結: QT 源碼之QT元對象系統和信號槽機制的內容介紹完了,希望本文對你有所幫助!

責任編輯:zhaolei 來源: CSDN博客
相關推薦

2011-06-23 14:40:13

Qt 信號

2011-06-09 09:45:35

Linux QT 信號

2011-06-15 14:38:01

QT 信號

2011-06-23 14:05:32

Qt 事件機制

2011-07-05 18:32:52

QT 信號 機制

2011-07-05 18:40:19

QT 信號 機制

2011-06-20 15:40:19

QT 信號

2011-06-13 10:21:25

QT 信號 槽機制

2011-06-28 15:47:13

Qt 信號

2011-06-23 13:25:42

QT 源碼 窗口

2011-06-23 11:16:39

Qt Excel

2011-06-24 10:05:51

QT 對象 父對象

2011-06-23 13:10:39

Python 對象機制

2011-06-30 17:51:17

QT 元類型 線程

2011-06-23 15:32:05

Qt Windows消息

2011-06-28 16:18:24

Qt QObject

2011-06-23 15:10:39

Qt 窗體

2023-10-07 08:21:35

PyQtPython

2021-12-23 15:07:40

QtC++編譯程序

2011-06-24 17:38:09

Qt 坐標 事件
點贊
收藏

51CTO技術棧公眾號

国产一区二区三区日韩精品| 91精品影视| 不卡视频免费播放| 国产ts人妖一区二区三区 | 久久久久久久蜜桃| 麻豆成人入口| 欧美美女一区二区| 国产二区视频在线| 97人人在线| 成人午夜激情片| 国产精品电影在线观看| av激情在线观看| 亚洲人成精品久久久| 欧美欧美午夜aⅴ在线观看| 妞干网视频在线观看| 国产精品秘入口| 丁香六月综合激情| 国产日产久久高清欧美一区| 久久久久久久久久一区二区三区| 国产精品嫩草影院在线看| 日韩一区国产二区欧美三区| 国产性xxxx18免费观看视频| 麻豆电影在线播放| 91视频在线看| 97超碰在线播放| 久久精品99北条麻妃| 欧美片第1页综合| 中文字幕欧美国内| 欧美 日本 国产| 日本一区二区三区播放| 欧美综合天天夜夜久久| 黄色一级视频在线播放| 成人日韩欧美| 国产精品嫩草影院av蜜臀| 好看的日韩精品| www.97av| 激情五月婷婷综合网| 国产精品成人aaaaa网站| 国产在线视频在线观看| 亚洲精品二区三区| 中文字幕日韩欧美精品在线观看| 国产精品一级黄片| 欧美成人基地| 精品国产伦一区二区三区观看体验| xxww在线观看| 亚洲www啪成人一区二区| 丁香五六月婷婷久久激情| 国产91视频一区| 成人日批视频| 亚洲猫色日本管| 在线观看视频黄色| 黄色免费在线网站| 亚洲视频一区二区在线观看| 亚洲精品国产一区| 在线中文资源天堂| 综合色天天鬼久久鬼色| 亚洲黄色一区二区三区| 国产高清免费av在线| 久久久久99精品国产片| 欧美日韩国产不卡在线看| 亚洲人午夜射精精品日韩| heyzo一本久久综合| 国产精品国产一区二区| 成人乱码一区二区三区| 成人久久18免费网站麻豆 | 欧美高清性猛交| 久草国产在线视频| 亚洲黄色一区| 国产91热爆ts人妖在线| 成人小视频在线播放| 日本在线播放一区二区三区| 国产精品视频一区二区高潮| 一区二区www| 激情深爱一区二区| 不卡一卡2卡3卡4卡精品在| 亚洲国产精品视频在线| 成人avav在线| 欧美午夜精品理论片a级大开眼界| 日av在线播放| 国产欧美日韩精品a在线观看| 亚洲成人蜜桃| 黄色在线免费看| 亚洲一区二区偷拍精品| 日韩欧美国产免费| jizzyou欧美16| 日韩一区二区三区免费观看 | 91美女精品福利| 欧美日韩最好看的视频| 国产午夜在线视频| 亚洲欧美另类图片小说| 日韩视频免费播放| 中文字幕日本一区二区| 欧美一级专区免费大片| 日韩精品一区二区三区高清免费| 亚洲最好看的视频| 日韩视频免费观看| 精品少妇theporn| 鲁大师影院一区二区三区| 国产欧美精品一区二区| 亚洲成人第一区| 久久久国产精华| 男人j进女人j| 国产精品极品美女在线观看| 这里只有精品视频在线观看| 在线观看国产免费视频| 欧美电影免费| 91av视频在线观看| 96亚洲精品久久久蜜桃| 99精品视频在线观看| 在线观看日韩羞羞视频| 精品众筹模特私拍视频| 91国偷自产一区二区三区成为亚洲经典 | 岛国av午夜精品| 一级淫片在线观看| 人人精品亚洲| 欧美美最猛性xxxxxx| 精品视频一二三区| 成人午夜视频在线| 最新黄色av网站| 在线国产成人影院| 亚洲精品国产品国语在线| 中文字幕电影av| 日本视频在线一区| 免费av一区二区三区| 欧洲性视频在线播放| 欧美无乱码久久久免费午夜一区 | 日韩亚洲欧美成人| 中文字幕免费观看| 99久久er热在这里只有精品15 | 国产呦小j女精品视频| 一精品久久久| 成人午夜高潮视频| 午夜免费视频在线国产| 欧美性猛交xxxx黑人| 年下总裁被打光屁股sp | 97人妻精品视频一区| www.欧美色图| 免费视频爱爱太爽了| 精品视频在线一区| 久久精品91久久香蕉加勒比| 中文字幕免费视频观看| 久久精品人人爽人人爽| 黄色动漫在线免费看| 中文字幕亚洲在线观看| 欧美成人中文字幕在线| 国产精品视频久久久久久| 国产精品系列在线| 国产aaaaa毛片| gogogo高清在线观看一区二区| 国产97在线|日韩| 欧美视频综合| 日韩欧美极品在线观看| 野花社区视频在线观看| 亚洲深夜激情| 久久这里精品国产99丫e6| 在线观看涩涩| 亚洲人成五月天| 91丝袜一区二区三区| 久久久噜噜噜久久人人看| 成年人观看网站| 国产videos久久| 国产精品视频网站| 国产福利在线播放麻豆| 日韩欧美在线网站| 久久久国产精品黄毛片| 成人福利视频网站| 国产又黄又大又粗视频| 国产乱码精品一区二区亚洲| 国产精品美女免费看| 欧美jizzhd69巨大| 日韩一区二区三区av| 国产一级片网址| 久久综合久久99| 免费看国产黄色片| 婷婷色综合网| 国产精品久久久久久久天堂第1集| 电影k8一区二区三区久久| 日韩av资源在线播放| www.国产毛片| 亚洲丝袜制服诱惑| 亚洲av人人澡人人爽人人夜夜| 亚洲一区久久| 亚洲一区三区电影在线观看| 久久视频免费| 欧美一级大片在线免费观看| 在线观看完整版免费| 日韩一区二区三区四区五区六区 | 美女隐私在线观看| 欧美成人精精品一区二区频| 69成人免费视频| 最新日韩在线视频| 国产精品久久不卡| 激情国产一区二区| 97国产在线播放| 欧美aaaaaaaaaaaa| 久久波多野结衣| 成人亚洲精品| 欧美中在线观看| av文字幕在线观看| 亚洲欧美综合图区| 午夜精品久久久久久久99热黄桃| 欧美日韩在线视频一区| 91高清免费看| 国产欧美一区二区三区鸳鸯浴 | 91成人噜噜噜在线播放| 国产97在线观看| 高清电影在线免费观看| 在线看欧美日韩| 农村少妇久久久久久久| 欧美日韩一卡二卡三卡| 一区二区三区视频免费看| 国产精品亲子伦对白| 免费看毛片的网站| 国产一区在线不卡| 亚洲欧美国产日韩综合| 在线观看日韩av电影| 中文字幕一区二区三区精彩视频 | 亚洲欧洲日夜超级视频| 91蝌蚪精品视频| 91久久精品久久国产性色也91| 久久uomeier| 韩国欧美亚洲国产| 欧美黑人xx片| 久久国产精品亚洲| 91在线品视觉盛宴免费| 亚洲精品在线视频| 免费国产羞羞网站视频| 欧美一级高清片在线观看| 在线免费观看av片| 欧美在线999| 手机看片久久久| 午夜精品久久久久久久久| 久久国产在线观看| 亚洲激情男女视频| 91日韩中文字幕| 亚洲欧美日韩国产手机在线| 中国美女黄色一级片| 欧美激情一区二区三区不卡| 法国伦理少妇愉情| 91免费视频观看| 一起草在线视频| av中文一区二区三区| 挪威xxxx性hd极品| 成人免费视频视频| 国产人妖在线观看| 懂色av噜噜一区二区三区av| 丰满少妇中文字幕| 国产精品一区二区三区网站| 亚洲国产日韩在线一区| 国产精品一区二区不卡| 亚洲国产综合av| 国产黑丝在线一区二区三区| 波多野结衣免费观看| 国产一区日韩二区欧美三区| 亚洲综合123| 国产91精品一区二区麻豆网站| 三级网站免费看| 成人综合婷婷国产精品久久| 四虎永久免费观看| 97se亚洲国产综合自在线不卡 | 日本中文字幕在线一区| 久久精品成人一区二区三区蜜臀| 日本成人7777| 欧美日韩精品免费观看视一区二区 | 精品国产乱码久久久久久久软件| 懂色av一区二区| 成人黄动漫网站免费| 狼人精品一区二区三区在线| 精品日本一区二区| 国产精品一区2区3区| 亚洲精品视频一区二区三区| 午夜片欧美伦| www精品久久| 免费永久网站黄欧美| 色多多视频在线播放| 国产精品亚洲а∨天堂免在线| 中文字幕在线国产| 久久尤物电影视频在线观看| 东方伊人免费在线观看| 亚洲精品亚洲人成人网在线播放| 久久久久黄色片| 日韩人体视频一二区| 中文字幕精品一区二| 欧美一区二区女人| 午夜国产在线视频| 中文字幕欧美日韩va免费视频| 欧美人动性xxxxz0oz| 日韩美女在线观看| www.欧美视频| 久久精品五月婷婷| 四虎成人av| 大肉大捧一进一出好爽视频| 美女mm1313爽爽久久久蜜臀| 亚洲色图欧美另类| 国产色产综合色产在线视频| 欧美日韩精品一区二区三区视频播放| 精品久久久久久中文字幕一区奶水 | 国产一区二区三区自拍| 欧美激情成人网| 国产精品综合一区二区三区| 波多野结衣av在线免费观看| 亚洲欧美另类综合偷拍| 天天操夜夜操视频| 日韩欧美自拍偷拍| fc2在线中文字幕| 欧美精品福利在线| 国产亚洲欧美日韩精品一区二区三区| 国产欧美日韩综合精品二区| 欧美大片aaaa| 欧美精品一区二区三区免费播放| 国产剧情av麻豆香蕉精品| 亚洲第一综合网| 天天爽夜夜爽夜夜爽精品视频| 亚洲最新av网站| 亚洲女人被黑人巨大进入al| 久草在线新免费首页资源站| 国产日产久久高清欧美一区| 蜜桃国内精品久久久久软件9| 日产精品久久久久久久蜜臀| 美女尤物国产一区| 男生草女生视频| 午夜久久久久久久久久一区二区| 国产巨乳在线观看| 一区二区三区视频在线| 在线免费看h| 国产日韩在线一区二区三区| 欧美激情1区| 午夜视频在线观| 国产精品久久久久精k8| 亚洲成熟少妇视频在线观看| 日韩经典中文字幕在线观看| 男女羞羞视频在线观看| 2019国产精品视频| 国产大片一区| 亚洲欧美视频二区| 国产精品素人一区二区| 亚洲av无码不卡| 国产偷国产偷亚洲清高网站| 99爱在线观看| 国产精品一区二区三区四区五区| 中文无码久久精品| 女人高潮一级片| 国产精品久久久久aaaa| 中文字幕乱码中文字幕| 一区二区三欧美| 偷拍中文亚洲欧美动漫| 日本在线观看一区| 日韩精品视频网站| 欧美激情 一区| 欧美性一区二区| 免费超碰在线| 91美女福利视频高清| 亚洲精品在线观看91| 在线观看视频你懂得| 亚洲综合丁香婷婷六月香| 性一交一乱一精一晶| 欧美极品少妇与黑人| 荡女精品导航| 欧美亚洲一二三区| 久久免费电影网| 欧美激情一区二区三区免费观看| 国产一区二区三区欧美| 久久久久黄色| 亚洲精品少妇一区二区| 成人免费视频国产在线观看| 国产做受高潮漫动| 亚洲欧美在线播放| 欧美极品影院| 在线视频福利一区| 国产精品综合av一区二区国产馆| 国产亚洲精品成人| 日韩av在线网页| 精品欧美日韩精品| 三年中文高清在线观看第6集 | 超碰97网站| 国产亚洲网站| 国产精品视频在| 日韩欧美一区二区三区在线| 天堂电影一区| 亚洲欧洲一区二区| 国产成人精品1024| 日韩手机在线视频| 久久久国产精品亚洲一区| 精品亚洲精品| 午夜免费看毛片| 亚洲成人手机在线| 97在线观看免费观看高清| 电影午夜精品一区二区三区 | 亚洲成人1区2区| 国产高清自拍视频在线观看| 3d精品h动漫啪啪一区二区| 免费日韩视频| 可以直接看的黄色网址| 国产偷亚洲偷欧美偷精品| 高清不卡一区| 久久综合久久色| 亚洲一区二区在线观看视频| 高清国产福利在线观看| 国产精品久久久久av福利动漫| 青青草国产成人99久久|