精品欧美一区二区三区在线观看 _久久久久国色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牛牛免费视频| 亚洲精品色午夜无码专区日韩| 国产高清不卡| 亚洲素人一区二区| 国产三区精品| 成人黄色免费网| 欧美亚韩一区| 在线视频精品一| 91porn在线| 成人福利一区二区| 午夜精品一区二区三区电影天堂| 亚洲精品国产精品国自产| 亚洲免费成人网| 视频在线观看91| 欧美极品少妇xxxxⅹ裸体艺术 | 91蜜桃在线观看| 懂色av中文一区二区三区| 亚洲第一精品夜夜躁人人爽| 国产av人人夜夜澡人人爽| 日本高清视频在线播放| proumb性欧美在线观看| 91情侣偷在线精品国产| 欧美日韩a v| 亚洲人成人一区二区三区| 精品国产一区二区在线| 国产人妻人伦精品1国产丝袜| 999精品嫩草久久久久久99| 欧美日韩在线影院| 日本人体一区二区| 国产福利在线播放麻豆| 国产精品入口麻豆九色| 欧美日韩在线精品| 五月婷中文字幕| 国产福利一区二区三区在线视频| 国产精品视频一区国模私拍| 亚洲欧美综合另类| 在线播放精品| 久久久久久久成人| 欧美成人精品一区二区免费看片| 成人a'v在线播放| 亚洲另类图片色| 国产xxxxxxxxx| 在这里有精品| 日韩亚洲欧美中文三级| 成人av毛片在线观看| 免费在线超碰| 久久久精品2019中文字幕之3| 久久av一区二区三区漫画| 神马午夜电影一区二区三区在线观看| 国产精品一区二区久久精品爱涩| 成人在线观看视频网站| 国产日韩一级片| 国产米奇在线777精品观看| 国产在线播放91| 一本一道人人妻人人妻αv| 免费在线成人网| 国产精品美女主播| 91精品国产乱码久久久| 国产一区二区不卡在线| 99视频日韩| 亚洲免费视频网| 99久久夜色精品国产网站| 狠狠色噜噜狠狠狠狠色吗综合| 成人免费淫片视频软件| 中文在线第一页| 葵司免费一区二区三区四区五区| 日韩午夜在线电影| 一本色道久久88亚洲综合88| 欧美人妻一区二区三区| 黄色不卡一区| 丝袜情趣国产精品| 国产真实乱在线更新| 中国成人一区| 国内精品久久久久久久久| 亚欧洲精品在线视频| 亚洲精品专区| 国产精品久久久久影院日本| 最近中文字幕av| 国内精品免费**视频| 3d动漫精品啪啪一区二区三区免费| 99久久久国产精品无码免费| 懂色av中文字幕一区二区三区| 精品国产aⅴ麻豆| 国产在线观看免费| 中文字幕日韩一区| 国产乱子伦精品无码专区| 精品众筹模特私拍视频| 欧美日韩国产精品一区| 激情五月婷婷久久| 精品国产一区二| 亚洲变态欧美另类捆绑| 亚洲а∨天堂久久精品2021| 9191国语精品高清在线| 亚洲国产日韩综合久久精品| 992tv成人免费影院| 免费黄色av片| 国产精品一区二区三区四区 | 这里视频有精品| 亚洲欧美日韩在线一区| 亚洲区一区二区三| 99在线精品免费视频九九视| 国产精品免费一区| 亚洲精品人妻无码| 国产喂奶挤奶一区二区三区| 国产激情片在线观看| 在线精品亚洲欧美日韩国产| 欧美精品 国产精品| 男人网站在线观看| 日韩精品网站| 欧美在线视频免费| www香蕉视频| 欧美激情一区二区三区蜜桃视频 | 久久久精品动漫| 国内精品久久久久久野外| 欧美日韩国产一区中文午夜| 手机在线国产视频| 亚洲天堂日韩在线| 欧美肥老妇视频| 夜夜嗨aⅴ一区二区三区| 99r国产精品| 国产91沈先生在线播放| 少妇高潮一区二区三区99| 日韩精品视频在线免费观看| 欧美精品乱码视频一二专区| 麻豆精品在线看| 欧美精品欧美精品| 888av在线视频| 欧美一级理论片| 精品一区二区三孕妇视频| 国产一区二区三区成人欧美日韩在线观看| 91青草视频久久| 在线观看a视频| 欧美在线一二三| 日本丰满少妇裸体自慰| 日韩视频二区| 国产精品一 二 三| 天堂网中文在线观看| 精品福利在线| 国产一区二区三区毛片| 好看的av在线| 99久久精品国产毛片| 男人添女荫道口喷水视频| 欧美2区3区4区| 麻豆乱码国产一区二区三区 | 美国黄色特级片| 日韩和欧美的一区| 色狠狠久久av五月综合| 欧美第一视频| 一个色综合导航| 国产又粗又猛又黄视频| 久久久久国产成人精品亚洲午夜| 国产97在线 | 亚洲| 久久久久97| 97精品在线观看| 亚洲人妻一区二区三区| 欧美日韩国产精品一区二区三区四区| 少妇户外露出[11p]| 亚洲巨乳在线| 久久综合久久久| 一个人www视频在线免费观看| 亚洲精品久久久久中文字幕二区| 亚洲一区欧美在线| 91丨九色丨尤物| 日本黄色三级大片| 成人3d精品动漫精品一二三| 国产欧美久久一区二区| 精产国品自在线www| 宅男在线国产精品| 一本色道久久88亚洲综合88| 一级黄色片大全| 日韩精彩视频在线观看| 日韩av不卡在线播放| 色999久久久精品人人澡69 | 日本一区免费在线观看| 日韩中文在线播放| 北条麻妃久久精品| 朝桐光av在线一区二区三区| 午夜国产精品影院在线观看| av网站免费在线播放| 日日摸夜夜添夜夜添国产精品| 亚洲一区二区三区欧美| 日韩精品久久久久久久软件91| 欧美精品成人91久久久久久久| 日韩大片b站免费观看直播| 在线观看欧美精品| 日本a级片视频| 久久综合久久综合久久| 加勒比av中文字幕| 日韩天堂av| 日韩一区av| 欧美激情麻豆| 国产精品初高中精品久久| 欧美13videosex性极品| 亚洲偷欧美偷国内偷| 国产精品一级二级| 五月婷婷激情综合| 69视频在线观看免费| 国产麻豆午夜三级精品| 丰满少妇被猛烈进入高清播放| 日韩毛片视频| 国产日韩欧美精品| 日日狠狠久久| 欧美在线视频一二三| www国产在线观看| 亚洲老司机av| 亚洲狼人综合网| 欧美日韩一区二区三区高清 | 亚洲女人****多毛耸耸8| 真人bbbbbbbbb毛片| 激情综合五月天| aaa毛片在线观看| 午夜精品网站| 亚洲国产精品123| 久久精品亚洲成在人线av网址| 成人日韩在线电影| 欧美性xxx| 欧美激情精品久久久久| av女优在线| 国产偷亚洲偷欧美偷精品| 亚洲va久久久噜噜噜无码久久| 欧美优质美女网站| 成人免费a视频| 亚洲午夜久久久久中文字幕久| www.xx日本| 国产亚洲一本大道中文在线| 在线综合亚洲欧美在线视频 | 99国产一区二区三精品乱码| 在线观看视频你懂得| 日韩电影在线观看一区| 国产伦精品一区二区三区四区视频_ | 日韩二区在线观看| 日本韩国欧美在线观看| 国产精品vip| 韩国黄色一级大片| 亚欧美无遮挡hd高清在线视频| 视频二区一区| 国产成人一区| 奇米影视首页 狠狠色丁香婷婷久久综合 | 国产精品久久久久久久av| 97超碰欧美中文字幕| 一边摸一边做爽的视频17国产| 国产精品一区二区视频| 亚洲欧美日本一区二区| 蜜桃视频免费观看一区| 亚洲xxxx2d动漫1| 日本大胆欧美人术艺术动态 | 福利一区二区在线观看| 久久久久亚洲av无码麻豆| 国产一区二区三区四区五区美女| 色天使在线观看| 精品一区二区三区蜜桃| 午夜剧场在线免费观看| 蜜臀av一区二区在线观看 | 欧美激情不卡| 91精品久久久久| 涩涩涩久久久成人精品| 成人天堂噜噜噜| 亚洲国产中文在线| 国产传媒一区二区| 日本中文字幕在线一区| 精品无人乱码一区二区三区的优势| 极品束缚调教一区二区网站| 精品久久一区二区三区蜜桃| 亚洲+变态+欧美+另类+精品| 欧美人xxxxx| 日韩欧美午夜| 路边理发店露脸熟妇泻火| 国产精品地址| 国产精品后入内射日本在线观看| 午夜亚洲影视| www.涩涩涩| 国产一区欧美二区| 99热超碰在线| 久久久久综合网| 久久久久麻豆v国产| 亚洲日本韩国一区| 国产污视频在线观看| 日韩欧美高清视频| 亚洲精品视频导航| 中文字幕这里只有精品| 国内精品模特av私拍在线观看| 漫画在线观看av| 国产精品第二页| 精品精品视频| 久久精品日产第一区二区三区乱码 | 欧美电影影音先锋| 国模私拍视频在线| 国产一区二区三区18| 少女频道在线观看高清| 欧美中文字幕在线观看| www.成人| 久久久人人爽| 亚洲第一偷拍| 欧美日韩在线中文| 国产在线精品一区在线观看麻豆| 久久久老熟女一区二区三区91| 国产欧美一区二区精品秋霞影院| 欧美卡一卡二卡三| 欧美性20hd另类| 国产wwwxxx| 一区二区亚洲精品国产| 日本大片在线播放| 国产精品美乳在线观看| 成人性生交大片免费看96| 色婷婷精品国产一区二区三区| 午夜日韩福利| 中文字幕一区二区三区四区在线视频| 国产精品综合一区二区三区| 大又大又粗又硬又爽少妇毛片| 亚洲欧美日韩小说| 懂色av蜜臀av粉嫩av分享吧最新章节| 91精品国产色综合久久ai换脸| 黄色av免费在线看| 欧美极品在线视频| 久久女人天堂| 欧美一区二区福利| 亚洲性图久久| 亚洲一区二区三区四区精品| 国产婷婷一区二区| 久久久午夜影院| 日韩欧美国产综合一区| 欧美三级黄网| 国产成人午夜视频网址| 老司机精品在线| 先锋影音男人资源| 奇米精品一区二区三区在线观看| 日韩av一二区| 亚洲成a人v欧美综合天堂下载 | 成人污视频在线观看| 亚洲色图27p| 欧美亚洲日本一区| 日本天堂影院在线视频| 69久久夜色精品国产7777| 超碰精品在线| 欧美视频在线第一页| 国模无码大尺度一区二区三区| 99久久99久久精品免费看小说.| 日韩欧美一区二区三区久久| 天天综合网在线观看| 欧美激情综合色| 国产精品国产精品国产专区| 亚洲视频一区在线| 中文字幕免费播放| 亚洲视频在线观看网站| xxxxxx欧美| 欧美一级片免费观看| 免费一级欧美片在线播放| 青青草视频播放| 欧美日韩另类视频| 色网站在线免费观看| 91av免费观看91av精品在线| 动漫视频在线一区| 日韩网站在线免费观看| 成人91在线观看| 色网站在线播放| 日韩精品视频免费专区在线播放| 范冰冰一级做a爰片久久毛片| 久久影视中文粉嫩av| 久久激情一区| 任你操精品视频| 欧美一区二区三区系列电影| 国产福利视频在线| 4444kk亚洲人成电影在线| 精品电影一区| 精品夜夜澡人妻无码av| 91高清视频免费看| 在线观看免费黄色| 亚洲自拍小视频| 亚洲精品裸体| 欧美成人国产精品一区二区| 欧美日韩精品综合在线| 国产精品实拍| 国严精品久久久久久亚洲影视| 香蕉亚洲视频| 一二三四在线观看视频| 91精品蜜臀在线一区尤物| av在线网页| 欧美色图亚洲自拍| 精品一区二区三区免费视频| 国产一级一片免费播放| 亚洲欧洲在线视频| 91精品亚洲一区在线观看| 成人免费视频91| 国产欧美日韩综合精品一区二区| 国产尤物在线观看| 久久琪琪电影院| 欧美日韩在线网站| xxxxwww一片| 一本到高清视频免费精品| 国产在线观看a| 美国av一区二区三区| 精品一区二区三区欧美| 一级片免费网址| 色一区av在线| 超碰97久久国产精品牛牛| 男操女免费网站| 午夜欧美一区二区三区在线播放| 国产综合在线观看| 国产欧美一区二区视频|